快捷搜索:  汽车  科技

unity生成c代码:unity动态执行C代码

unity生成c代码:unity动态执行C代码using UnityEditor; using UnityEngine; [CustomEditor(typeof(DynamicCodeHelper))] public class DynamicCodeEditor : Editor { string runCode = @"Debug.LogError(""test your code here!"");"; public override void OnInspectorGUI() { GUILayout.Label("DynamicC#Code" GUILayout.Width(100)); runCode = GUILayout.TextArea(runCode GUILayout.Height(5

好久没写文章了,主要还是之前公司项目时间紧,任务重,导致下班了就没心情开电脑了,到家倒头就睡了,今天趁稍微空闲就赶紧把最近写的一个小功能记录下,以便以后能用上。

unity生成c代码:unity动态执行C代码(1)

unity生成c代码:unity动态执行C代码(2)

公司项目由于以lua为主,所以很容易实现动态执行代码,举个例子,游戏运行中,某个数据显示不对,这个时候就能在不关闭游戏运行的情况下,直接将写好的代码粘贴进输入框执行,就能知道是服务器传的数据问题还是客户端的问题。再举个例子,在播放新手动画时,策划说某个角色的点的位置不好,得换个位置,虽然我们能直接把角色拖到某个位置上来看效果,但如果有寻路的话,就没法知道这个点是不是能通过寻路来走到了,这个时候就可以写一段代码让角色自己走到想要去的点来看效果,而不用关闭游戏,然后写完代码再走一堆流程到需要测试的地方看效果。个人觉得能节省一点时间。那么问题来了,lua能这么做,C#能不能呢?于是我搜索了很多网页,终于让我找到了方法,不过还是有一些小问题,比如UnityEngine.dll文件加载不了,自己编写的脚本的所在的dll名字,还有就是像上图一样有输入框的地方等。以下就是实现动态执行C#代码的脚本。

类名:DynamicCodeHelper

using System; using System.Reflection; using Microsoft.CSharp; using System.CodeDom.Compiler; using System.Text; using UnityEngine; public class DynamicCodeHelper : MonoBehaviour { public void ExcuteDynamicCode(string codeStr="") { string[] strList = codeStr.Split(';'); // 1.CSharpCodePrivoder CSharpCodeProvider objCSharpCodePrivoder =new CSharpCodeProvider(); // 2.ICodeComplier ICodeCompiler objICodeCompiler = objCSharpCodePrivoder.CreateCompiler(); // 3.CompilerParameters CompilerParameters objCompilerParameters =new CompilerParameters(); objCompilerParameters.ReferencedAssemblies.Add("System.dll"); objCompilerParameters.ReferencedAssemblies.Add(Application.dataPath.Replace("Assets" "Library") "/ScriptAssemblies/Assembly-CSharp.dll"); objCompilerParameters.ReferencedAssemblies.Add(Application.dataPath.Replace("Assets" "MyDll") "/UnityEngine.CoreModule.dll");//尝试过通过写文本配置来加载,结果不行会报错,如果有大佬解决了请留言告诉我,万分感谢 objCompilerParameters.GenerateExecutable =false; objCompilerParameters.GenerateInMemory =true; // 4.CompilerResults CompilerResults cr = objICodeCompiler.CompileAssemblyFromSource(objCompilerParameters GenerateCode(strList)); if (cr.Errors.HasErrors) { Debug.LogError("编译错误:"); foreach (CompilerError err in cr.Errors) { Debug.LogError(err.ErrorText); } } else { // 通过反射,调用DynamicCode的实例 Assembly objAssembly = cr.CompiledAssembly; object objDynamicCode = objAssembly.CreateInstance("DynamicCodeGenerate.DynamicCode"); MethodInfo objMI = objDynamicCode.GetType().GetMethod("CodeExecute"); objMI.Invoke(objDynamicCode null); } } static string GenerateCode(string[] strList) { StringBuilder sb =new StringBuilder(); sb.Append("using System;"); sb.Append(Environment.NewLine); sb.Append("using UnityEngine;"); sb.Append(Environment.NewLine); sb.Append("namespace DynamicCodeGenerate"); sb.Append(Environment.NewLine); sb.Append("{"); sb.Append(Environment.NewLine); sb.Append(" public class DynamicCode"); sb.Append(Environment.NewLine); sb.Append(" {"); sb.Append(Environment.NewLine); sb.Append(" public void CodeExecute()"); sb.Append(Environment.NewLine); sb.Append(" {"); sb.Append(Environment.NewLine); foreach (string str in strList) { if (str != "") { sb.Append(string.Format(" {0};" str.Replace("\n" ""))); sb.Append(Environment.NewLine); } } sb.Append(" }"); sb.Append(Environment.NewLine); sb.Append(" }"); sb.Append(Environment.NewLine); sb.Append("}"); string code = sb.ToString(); Debug.LogError(code); return code; } }

unity生成c代码:unity动态执行C代码(3)

unity生成c代码:unity动态执行C代码(4)

unity生成c代码:unity动态执行C代码(5)

简单说明:1.UnityEngine.dll已经被分割了,所以这里加载的是UnityEngine.CoreModule.dll,我的路径在E:\Unity 2019.2.4f1\Unity\Editor\Data\Managed\UnityEngine\UnityEngine.CoreModule.dll,也就是在编辑器安装路径的Editor\Data\Managed\UnityEngine\UnityEngine.CoreModule.dll。我是创建了和Assets同级的一个文件夹,命名为MyDll,这样一些需要加载的dll我就全放这里了,

2.我们在unity新增的C#脚本都是在Assembly-CSharp.dll这个程序集里,而这个程序集的路径就是在和Assets同级的Library底下的ScriptAssemblies文件夹里。

3.Editor脚本如下。

类名:DynamicCodeEditor

using UnityEditor; using UnityEngine; [CustomEditor(typeof(DynamicCodeHelper))] public class DynamicCodeEditor : Editor { string runCode = @"Debug.LogError(""test your code here!"");"; public override void OnInspectorGUI() { GUILayout.Label("DynamicC#Code" GUILayout.Width(100)); runCode = GUILayout.TextArea(runCode GUILayout.Height(500)); if (GUILayout.Button("RunAnyCode")) { RunAnyCode(runCode); } base.OnInspectorGUI(); } public void RunAnyCode(string code) { var t = target as DynamicTest; t.ExcuteDynamicCode(code); } }

这样就能在输入框中写代码,并动态执行了。

猜您喜欢: