1. 程式人生 > >在unity執行時動態編譯unity指令碼程式碼並生成dll庫

在unity執行時動態編譯unity指令碼程式碼並生成dll庫

由於unity並不完全支援所有的c#支援的dll庫,如:Mircrosoft.CSharp.dll 就不支援,所以unity在執行時並不能動態編譯指令碼,我的做法是利用unity與c#控制檯程式進行socket通訊達到在unity執行時動態編譯unity指令碼的目的,把unity安裝目錄下的UnityEngine.dll庫引入到c#工程中。下面並沒有給出socket通訊的程式碼,需要自己實現,不過實現起來比較簡單,把unity傳來的字串程式碼傳入下面類OnLineProgramming的方法TestCompiler即可。

我把主要功能程式碼封裝在一個類中,程式碼如下:

using  System;

using  System.Collections.Generic;

using  System.Linq;

using  System.Text;

using  Microsoft.CSharp;                                             //需要自己新增

using  System.CodeDom.Compiler;                             //需要自己新增

using  System.Reflection;                                          //反射名稱空間

using  UnityEngine;                                                   //需要自己新增,再強調一下,得新增UnityEngine.dll引用

 namespace  線上程式設計伺服器端

{

   internal class  OnLineProgramming

   {

       CSharpCodeProvider  provider;

       CompilerParameters  parameters;

       public OnLineProgramming() {

            //定義c#程式碼容器

            provider = new   CSharpCodeProvider();

            parameters = new   CompilerParameters();     

       }

       public string  TestCompiler(string  code)        //引數code是unity傳來的指令碼程式碼,返回值是編譯後的結果

       {

            StringBuilder  sb = new StringBuilder();                 

            try

            {

                //動態新增dll

               parameters.ReferencedAssemblies.Add("UnityEngine.dll");

               parameters.ReferencedAssemblies.Add("System.dll");

               parameters.ReferencedAssemblies.Add("System.Data.dll");

               parameters.ReferencedAssemblies.Add("System.Xml.dll");

                //True - 生成在記憶體中, false - 生成在外部檔案中

                parameters.GenerateInMemory =false;

                //True - 生成 exe, false - 生成 dll

                parameters.GenerateExecutable =false;

                parameters.OutputAssembly = "Test.dll";         //編譯後的dll庫輸出的名稱,會在bin/Debug下生成Test.dll庫

                //取得編譯結果

                CompilerResults  results = provider.CompileAssemblyFromSource(parameters, code);

                if(results.Errors.HasErrors)

                {

                    foreach(CompilerError error in results.Errors)

                    {

                        sb.AppendLine(String.Format("Error({0}): {1}", error.Line, error.ErrorText));

                    }

                    returnsb.ToString();                                     //編譯不通過,返回錯誤資訊

                }

                else

                {

                    return"Ok";                                             //編譯通過,返回Ok

                }

            }

            catch(Exception)

            {

                Console.WriteLine("拋異常了");

                returnsb.ToString();

            }

       }

   }

}

指令碼測試程式碼如下,可以把下面的程式碼寫在一個txt檔案中,通過IO操作把下面的程式碼轉成字串,再傳入上面類的方法TestCompiler中,這裡提供一下思路,具體程式碼就不提供了。

using System;
using UnityEngine;
 
 namespace First
{
       public class Program: MonoBehaviour
       {
           void Start()
          {
              Vector3 vec = new Vector3(0f,1f,3f);
              GameObject go = GameObject.Find("Cube");                      
              go.transform.Translate(new Vector3(0f,0f,0f));                                
                               
          }


           void Update(){
                float time=Time.deltaTime;
                Debug.Log("我是dll方法");
          }
       }
 }

具體如何在unity中使用剛剛編譯好的dll庫,並把指令碼動態新增到遊戲物體上,待續!!!!