在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庫,並把指令碼動態新增到遊戲物體上,待續!!!!