由于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库,并把脚本动态添加到游戏物体上,待续!!!!