static void GenerateCode() { UnityEngine.Debug.LogError("编译"); var code = @" using UnityEditor; using TBC.Timeline; namespace TBC.Editor.Timeline { [CustomEditor(typeof(TBCParticleClip))] public class BattleParticleInspector : UnityEditor.Editor { public override void OnInspectorGUI() { } } }"; CodeDomProvider provider = CodeDomProvider.CreateProvider("C#");//创建编译器 CompilerParameters options = new CompilerParameters();//创建编译器参数 options.ReferencedAssemblies.Add("E:/TLBB/game/client/TLProject/Library/ScriptAssemblies/TBC.Framework.Editor.dll"); options.ReferencedAssemblies.Add("D:/Program Files/Unity 2019.4.35f1/Editor/Data/Managed/UnityEditor.dll");//为当前程序集添加引用 options.ReferencedAssemblies.Add("D:/Program Files/Unity 2019.4.35f1/Editor/Data/Managed/UnityEngine/UnityEngine.CoreModule.dll"); options.ReferencedAssemblies.Add("E:/TLBB/game/client/TLProject/Library/ScriptAssemblies/Unity.Timeline.dll"); options.ReferencedAssemblies.Add("E:/TLBB/game/client/TLProject/Library/ScriptAssemblies/TBC.Framework.dll"); options.ReferencedAssemblies.Add("D:/Program Files/Unity 2019.4.35f1/Editor/Data/Managed/UnityEngine.dll"); options.ReferencedAssemblies.Add("E:/TLBB/game/client/TLProject/Library/ScriptAssemblies/Unity.Timeline.Editor.dll"); options.GenerateExecutable = false;// 是否生成exe文件 options.GenerateInMemory = true;// 是否在内存输出 options.OutputAssembly = "E:/TLBB/game/client/TLProject/Library/AutoGenerate.dll"; CompilerResults cr = provider.CompileAssemblyFromSource(options, code);//直接执行 if (cr.Errors.HasErrors) { UnityEngine.Debug.LogError("编译错误:"); foreach (CompilerError err in cr.Errors) UnityEngine.Debug.LogError(err.ErrorText); } else { UnityEngine.Debug.Log("编译成功!"); } Assembly[] arr = AppDomain.CurrentDomain.GetAssemblies(); foreach (var ass in arr) { if (ass.FullName.Contains("AutoGenerate")) { UnityEngine.Debug.LogError("-------在当前域中--------"); UnityEngine.Debug.LogError(ass.FullName); } } }
命名空间
using System.Reflection; //动态编译用的 using System.CodeDom.Compiler;
注意点:
1.引用的dll必须填写绝对路径,否则找不到
2.如果引用的dll引用了其他的dll,也需要添加,先后顺序无所谓,如果没有引用会报错,根据报错引用即可
3.options.GenerateInMemory 与 options.OutputAssembly 需要设置,当 options.GenerateInMemory = true 且 options.OutputAssembly 有路径,路径有效即可,位置随意,那么动态编译后会自动被Unity的域加载,如果需要使用,反射即可
4.生成的UnityEditor相关的dll,如上面,虽然被Unity加载了,但无法执行,只能把dll放到unity的Asset下才行
案例说明
TBCClipInspector 是我放在自定义程序集 TBC.Framework.Editor.dll (这个Dll引用了Unity.Timeline.Editor.dll,TBCClip里引用了Unity.Timeline.dll)下的一个代码,主要是用于隐藏 Inspector面板的Script属性,代码如下
namespace TBC.Editor.Timeline { [CustomEditor(typeof(TBCClip))] public class TBCClipInspector : UnityEditor.Editor { public override void OnInspectorGUI() { EditorGUI.BeginChangeCheck(); serializedObject.Update(); SerializedProperty property = serializedObject.GetIterator(); bool expanded = true; while (property.NextVisible(expanded)) { expanded = false; if (SkipField(property.propertyPath)) continue; EditorGUILayout.PropertyField(property, true); } serializedObject.ApplyModifiedProperties(); EditorGUI.EndChangeCheck(); } static bool SkipField(string fieldName) { return fieldName == "m_Script"; } } }
所以如果继承TBCClip的类想有这个功能,对应的Inspector代码要继承TBCClipInspector,这才想设计一个属性标签用来动态生成对应的Inspector代码,可惜生成出来的dll必须放到Asset下才生效,失去了一开始的意义,(还不如直接生成代码文件),后续会用Dll注入试一下,本文只是记录实验过程,以及动态编译的方法
文章评论