最近有个需求是想让程序解析策划编辑一个文本生成一段CG,内容使用大致是这样

cgSetCameraEx(118.6324,30.71189,75.55666,45,-45,0,0)
cgCloneMyPlayer(1)
cgSetPosDir(1,109,80,0)
cgSetCameraEx(114.18,23.17,96.9,11.51974,-61.49661,-3.384705,3.5)
cgCreateActor(2,25,108,100,90)
cgWait(0.2)
cgMove(1,109.7,100,9,false)
cgWait(3)
cgFaceToActor(1,2)
cgWait(1.5)
cgPopTalk(1,1,2)

  

我的做法是借助一个第三方库NCalc,把自定义的函数注册到解析器里,让解析器去Load这段文本

using UnityEngine;
using System.Collections;
using NCalc;
using System.Collections.Generic;
using System; //解析字符串表达式执行函数 public class CallFunctionScript
{
//缓存函数表
private readonly Dictionary<string, Func<Expression[], object>> mRegisterFunctions = new Dictionary<string, Func<Expression[], object>>(); //注册可被执行的函数
//注册的函数格式满足 public static object Func(Expression[] args)
//函数返回值不能是null,如果不需要返回值可以返回1
public void RegisterFunction(string funcName, Func<Expression[], object> func)
{
if (!mRegisterFunctions.ContainsKey(funcName))
{
mRegisterFunctions.Add(funcName, func);
}
else
{
UnityEngine.Debug.LogError("duplicate func " + funcName);
}
} //反注册所有函数
public void UnRgisterAllFunction()
{
mRegisterFunctions.Clear();
} //执行函数
public object Execute(string expression)
{
var exp = new Expression(expression); //函数代理
exp.EvaluateFunction += delegate(string name, FunctionArgs args)
{
Func<Expression[], object> func;
if (mRegisterFunctions.TryGetValue(name, out func))
{
object result = null;
try
{
result = func(args.Parameters);
}
catch (Exception ex)
{
UnityEngine.Debug.LogError("Execute "+name + "() Error:" + ex.ToString());
}
finally
{
args.Result = result;
}
}
else
{
UnityEngine.Debug.LogError("Can't find function [" + name+"]");
}
}; try
{
return exp.Evaluate();//执行函数
}
catch (Exception ex)
{
Debug.LogError("Evaluate \"" + expression + "\" Error: "+ex.ToString());
return null;
}
}
}

  

//被注册的函数如这样

public static class CGFunctionWrapper
{
public static object cgCloneMyPlayer(Expression[] args)
{
if (args.Length < 1)
{
Logger.Error("cgCloneMyPlayer() args<[1]");
return 0;
}
PlayCG.Instance.cgCloneMyPlayer(
Convert.ToInt32(args[0].Evaluate())
);
return 1;
}
}

  

使用方法

public CallFunctionScript mExecutor = new CallFunctionScript();

mExecutor.RegisterFunction("cgCloneMyPlayer", CGFunctionWrapper.cgCloneMyPlayer);

mExecutor.Execute("cgCloneMyPlayer(1)");

  

Unity3d 解析文本执行已注册的自定函数的更多相关文章

  1. springIOC源码解析之BeanDefinition的注册

    ApplicationContext类结构 context是一个存储上下文结构的东西,里面会引用BeanFactory  BeanFactory类结构 我们从这句代码开始分析,(本文spring采用的 ...

  2. 解决IE11出现异常SCRIPT5011:不能执行已释放Script的代码

    功能概述: 最近做了一个教育科研系统,由于时间比较紧,所以能集成的功能都尽量做到了一起,其中一个上传附件的功能,在基类控制器BaseController 中建了一个Action返回视图,其他需要上传附 ...

  3. Python 一键拉取Git分支源码自动解析并执行SQL语句

    基于Python实现自动拉取Git分支源码自动解析并执行SQL语句 by:授客 QQ:1033553122 1.代码用途 开发过程中,研发人员会提交SQL更新脚本到Git源码库,然后测试负责去拉取这些 ...

  4. 【Dubbo 源码解析】04_Dubbo 服务注册&暴露

    Dubbo 服务注册&暴露 Dubbo 服务暴露过程是通过 com.alibaba.dubbo.config.spring.ServiceBean 来实现的.Spring 容器 refresh ...

  5. [SQL Server]无法创建 SSIS 运行时对象,请验证 DTS.dll 是否可用及是否已注册

    很大可能是SQL Server Management Studio(SSMS)版本与当前操作系统不兼容造成的,与数据库本身没有关系,这种情况基本无解,不过可以使用其他机器连本机数据库导入导出数据. 今 ...

  6. ie11 SCRIPT5011:不能执行已释放Script的代码

    依照我遇到的问题为例: (我的页面结构为:父页面中嵌套有iframe子页面) 1.造成这种情况的原因是:父页面初始化声明变量a为数组(数组对象是引用类型,赋值传递的是地址),创建iframe子页面后给 ...

  7. RequestMapping 注解的解析、匹配、注册

    RequestMapping 注解的解析.匹配.注册 1)创建 RequestMappingHandlerMapping 实例时会触发 afterPropertiesSet 调用. 2)读取容器中所有 ...

  8. 我该如何学习spring源码以及解析bean定义的注册

    如何学习spring源码 前言 本文属于spring源码解析的系列文章之一,文章主要是介绍如何学习spring的源码,希望能够最大限度的帮助到有需要的人.文章总体难度不大,但比较繁重,学习时一定要耐住 ...

  9. JS的解析与执行过程

    JS的解析与执行过程 全局中的解析和执行过程 预处理:创建一个词法环境(LexicalEnvironment,在后面简写为LE),扫描JS中的用声明的方式声明的函数,用var定义的变量并将它们加到预处 ...

随机推荐

  1. 程序日志输出实现-Log4j

    学习开发的过程中,我们都应该用过System.out.println():来做一些调试工作,有时候确实很有用有没有.但是这种简单粗暴的方式让程序中到处存在着sysout.这种方式难免会有性能的影响,维 ...

  2. MySQL分表自增ID解决方案(转)

    当我们对MySQL进行分表操作后,将不能依赖MySQL的自动增量来产生唯一ID了,因为数据已经分散到多个表中. 应尽量避免使用自增IP来做为主键,为数据库分表操作带来极大的不便. 在postgreSQ ...

  3. android自定义控件(8)-利用onMeasure测量使图片拉伸永不变形,解决屏幕适配问题

    使用ImageView会遇到的问题 在Android应用中,都少不了图片的显示,ImageView,轮播图,ViewPager等等,很多都是来显示图片的,很多时候,我们都希望图片能够在宽度上填充父窗体 ...

  4. webapi支持跨域访问

    写在前面 在实际应用中,跨域请求还是比较常见的,如何上接口直接支持跨域的访问呢? demo 场景项目A有个接口用来获取用户列表,现在项目b也有个功能需要加载用户列表.这两个项目在两个域名下,至少端口好 ...

  5. Promise编程基础

    (一) Promise基础     所谓Promise,简单说就是一个容器,里面保存着某个未来才会结束的事件(通常是一个异步操作)的结果.从语法上说,Promise是一个对象,从它可以获取异步操作的消 ...

  6. 获取指定版本号svn

    代码需求获取 svn update  svnworkpath --username xxx --password xxx -r r464 r464 为指定版本号 可以获取指定版本号的代码 也 也可以在 ...

  7. 【CISP笔记】安全漏洞与恶意代码(1)

    恶意代码 类型二进制代码.脚本语言.宏语言等表现形式病毒.蠕虫.后门程序.木马.流氓软件.逻辑炸弹等 恶意代码的传播方式(1)移动存储 自动播放功能.Windows默认.自动执行autorun.inf ...

  8. 2015年11月26日 Java基础系列(一)之String与StringBuffer与StringBuilder的区别

    序,StringBuffer是线程安全的,StringBuilder是线程不安全的,但是StringBuilder操作速度快,因此在使用时要根据场景合理选择. StringBuffer和StringB ...

  9. [译]git rebase

    rebase就是重新定义你分支的起点, 分支上的commit将生成对应的新的commit并放在你指定的新的起点commit后, 分支上的老commit将被删除. rebase就是将你的分支从一个com ...

  10. 第二章平稳时间序列模型——AR(p),MA(q),ARMA(p,q)模型及其平稳性

      1白噪声过程: 零均值,同方差,无自相关(协方差为0) 以后我们遇到的efshow如果不特殊说明,就是白噪声过程. 对于正态分布而言,不相关即可推出独立,所以如果该白噪声如果服从正态分布,则其还将 ...