1.C#層:利用.NET framework的CodeDom或Mono的Evaluator動態編譯解釋CS腳本
2.IL層:利用System.Reflection.Emit或Mono.Cecil動態生成IL指令並執行
3.造輪子自己實現IL解釋器(取代.NET或Mono的IL解釋器,這種方案可以繞過蘋果實現熱更新)
4.直接調用Mono的編譯器進行編譯生成dll,例如Win平台"..\Mono\bin\gmcs.bat"
參考:
- Clearscript、paxScript.NET
-
Dynamically executing code in .Net (比較不錯,他還提供了個wwScripting,方便使用,還支持將代碼加載到新的AppDomain)
CodeDom:
經過最新研究,這玩意其實就是去調用gmcs來生成代碼的,跟直接用gmcs沒差,在Unity編輯器里可以直接用,但打包出來就不行了,因為認不出gmcs的路徑
微軟鏈接:https://msdn.microsoft.com/en-us/library/saf5ce06(v=vs.110).aspx
不生成程序,直接寫在內存並調用生成的內容:http://stackoverflow.com/questions/24871955/c-sharp-compilerresults-generateinmemory
1.動態編譯CS代碼
作者:知乎用戶 鏈接:https://www.zhihu.com/question/31230641/answer/51098145 來源:知乎 著作權歸作者所有。商業轉載請聯系作者獲得授權,非商業轉載請注明出處。 using System; using System.Collections.Generic; using System.Linq; using Microsoft.CSharp; using System.CodeDom.Compiler; class Program { static void Main(string[] args) { var csc = new CSharpCodeProvider(new Dictionary<string, string>() { { "CompilerVersion", "v3.5" } }); var parameters = new CompilerParameters(new[] { "mscorlib.dll", "System.Core.dll" }, "foo.exe", true); // 生成exe,若為false,則生成dll parameters.GenerateExecutable = true; CompilerResults results = csc.CompileAssemblyFromSource(parameters, @"using System.Linq; class Program { public static void Main(string[] args) { var q = from i in Enumerable.Range(1,100) where i % 2 == 0 select i; } }"); results.Errors.Cast<CompilerError>().ToList().ForEach(error => Console.WriteLine(error.ErrorText)); } }
這種方法方便,強大,但缺點是不支持打包后的版本(不管是PC還是安卓,畢竟在Editor里有集成msc,打包后沒有),即使你將Unity的PlayerSetting里的Api Compatibitility Level設置為.NET 2.0也沒辦法,頂多是加入了namespace的引用,能在代碼里調用和編譯通過而已,但實際運行起來,還是會報錯:

官方論壇里有人遇到同樣的錯誤:http://answers.unity3d.com/questions/309490/is-it-possible-to-compile-and-run-c-code-on-the-fl.html
據說Xamarin支持?沒試過:https://developer.xamarin.com/api/namespace/System.CodeDom/
Evaluator:
這玩意其實不錯,但由於Unity目前只支持到.net 3.5,而3.5版的Mono.CSharp的Evaluator又比較爛,不支持類跟函數,只能解析簡單的語句
- 小試牛刀C#作為腳本語言執行解密
- https://forum.unity3d.com/threads/mono-csharp-evaluator.102162/
- http://answers.unity3d.com/questions/309490/is-it-possible-to-compile-and-run-c-code-on-the-fl.html
public class Data { public static int n = 0; public static GameObject go = null; } Mono.CSharp.Evaluator.Init(new string[] {} ); Assembly a = Assembly.GetExecutingAssembly(); Mono.CSharp.Evaluator.ReferenceAssembly(a); Mono.CSharp.Evaluator.Run("Data.n=Data.n+5;"); Debug.Log(Data.n); //5
支持在PC跟安卓上,IOS不行
調用Mono編譯器動態編譯:
CodeDom是比較完美的解決方案,無奈打包后的程序里的mono只包含runtime部分,沒有編譯部分工具,所以會導致打包后運行失敗,
所以Github(mcs-ICodeCompiler)上已經有大佬將mono里的msc部分單純提取出來,編譯成一個dll,供項目調用。
原理很簡單,CodeDom不是需要msc么?直接將所需的程序集部分提供給它就行,這部分很小,近1M左右,如果是整個mono項目,那非常巨大,估計幾十M。
注意:這種方法需要你的Unity項目必須是.NET 2.0,而不是.NET 2.0 Sub,如果是sub也所謂,直接將完整版的.NET 2.0里的System.dll替換進來即可。
注意2:CodeDom目前有個BUG,就是不支持Enum,若使用會使程序崩潰: https://bugzilla.xamarin.com/show_bug.cgi?id=24607
