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注入试一下,本文只是记录实验过程,以及动态编译的方法
文章评论