zoukankan      html  css  js  c++  java
  • 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)");
    

      

  • 相关阅读:
    EasyDarwin开源平台直播架构
    EasyDarwin开源平台直播架构
    ffmpeg推送,EasyDarwin转发,vlc播放 实现整个RTSP直播
    ffmpeg推送,EasyDarwin转发,vlc播放 实现整个RTSP直播
    开源G711(PCMA、PCMU)/G726转AAC项目EasyAACEncoder
    开源G711(PCMA、PCMU)/G726转AAC项目EasyAACEncoder
    RTSP/RTMP/HLS/HTTP流媒体播放器EasyPlayer
    开源流媒体播放器EasyPlayer
    vs添加对dll的引用
    vs添加对dll的引用
  • 原文地址:https://www.cnblogs.com/mrblue/p/5231930.html
Copyright © 2011-2022 走看看