最近有个需求是想让程序解析策划编辑一个文本生成一段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. chrome调试文章

    http://blog.csdn.net/a6225301/article/details/20207191#t1 http://www.360doc.com/content/13/1220/11/8 ...

  2. 本地wampserver如何配置伪静态

    本地wamp实现虚拟主机后,我把自己的站放进去就出现了500错误看日志看到.htaccess: Invalid command ‘RewriteEngine’, perhaps misspelled ...

  3. Hadoop生态系统

    Hadoop 生态圈

  4. Redis在WEB开发中的应用与实践

    Redis在WEB开发中的应用与实践 一.Redis概述: Redis是一个功能强大.性能高效的开源数据结构服务器,Redis最典型的应用是NoSQL.但事实上Redis除了作为NoSQL数据库使用之 ...

  5. hdu3729 I'm Telling the Truth (二分图的最大匹配)

    http://acm.hdu.edu.cn/showproblem.php?pid=3729 I'm Telling the Truth Time Limit: 2000/1000 MS (Java/ ...

  6. Linux内核循环链表经典分析和移植

    为什么说这个链表做的经典呢,哥哥我从Linux内核里边儿扣出来的,要么怎么说内核不是一般人能写的,这代码太TM优美了! 这里有一篇参考文章:http://isis.poly.edu/kulesh/st ...

  7. django 文件上传

    模板文件: <form method='post' action='/script/upload/' enctype="multipart/form-data" accept ...

  8. admin site

    基本步骤: 1.添加 'django.contrib.admin' 到 INSTALL_APP 设置中. 2.再添加四个依赖项: 'django.contrib.auth', 'django.cont ...

  9. 遇到了IAR烧写程序出错,附解决办法The stack plug-in failed to set a breakpoint on "main"

    今天做无线串口调试的时候用IAR7.51往CC2530无线模块烧程序的时候遇到了问题: 先是下载过程中有许多警告,然后就是提示无法跳断点,找不到main方法,每次烧程序都出现: The stack p ...

  10. isNaN() 确认是否是数字

    isNaN(x): 当变量 x 不是数字,返回 true: 当变量 x 是其他值,(比如,1,2,3),返回false.