Unity3d 解析文本执行已注册的自定函数

最近有个需求是想让程序解析策划编辑一个文本生成一段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)");

  

posted @ 2016-03-01 17:43  MrBlue  阅读(666)  评论(0编辑  收藏  举报