Unity 使用 Unity 直接编译外部 DLL
原因
Unity 集成了 Mono 编译器,所以在 Unity 里面新建 C# 脚本的时候,会自动进行编译。那么,思考可以不可以借助 Unity 的编译接口,来编译外部 DLL 文件。查找 Unity 编辑器的接口,发现有个 API:
那么,来测试下这个接口。
C# Code
1
2 3 4 |
public static string[] CompileCSharp(string[] sources, string[] references, string[] defines, string outputFile)
{ return MonoCSharpCompiler.Compile(sources, references, defines, outputFile); } |
测试准备
新建两个文件夹,一个放 Unity 测试工程,一个放外部 DLL 的源码文件,如下所示:
其中,C# 文件 MyUtilities.cs 代码如下:
C# Code
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
using System;
namespace DLLTest { public class MyUtilities { public int c; public void AddValues(int a, int b) { c = a + b; } public static int GenerateRandom(int min, int max) { System.Random rand = new System.Random(); return rand.Next(min, max); } } } |
编辑器脚本文件 MyCompile.cs 代码如下:
C# Code
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
using System.IO;
using UnityEditor; using UnityEngine; public class MyCompile { [MenuItem("Tool/My Compile")] private static void DoMyCompile() { string srcPath = Path.Combine(Application.dataPath, "../../TestDLL"); string[] sources = new[] {Path.Combine(srcPath, "MyUtilities.cs")}; string[] references = new string[0]; string[] defines = new string[0]; string outputFile = Path.Combine(Application.dataPath, "TestDLL.dll"); string[] msgs = EditorUtility.CompileCSharp(sources, references, defines, outputFile); foreach (var msg in msgs) { Debug.Log(msg); } string dllFile = "Assets/TestDLL.dll"; if (File.Exists(dllFile)) { AssetDatabase.ImportAsset(dllFile, ImportAssetOptions.ForceUpdate); } } } |
测试运行
点击菜单栏 "Tool/My Compile",等待执行完毕,可以看到如下:
可以看到已经生成了 DLL,并且其对应的 mdb 文件,也自动生成了。
新建个 Unity 脚本文件,来测试是否调用正常,代码如下:
运行编译,可以看到报告缺少引用,如下所示:
C# Code
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
using UnityEngine;
using DLLTest; public class Test : MonoBehaviour { void Start() { MyUtilities utils = new MyUtilities(); utils.AddValues(2, 3); print("2 + 3 = " + utils.c); } void Update() { print(MyUtilities.GenerateRandom(0, 100)); } } |
挂载到场景物体上,运行显示如下:
证明可以调用正确。
测试错误
接下去测试外部 DLL 源码错误的情况下,会不会报告所在的错误。更改 MyUtilities.cs 里的 AddValues 方法,让其参数变量错误,更改为如下:
C# Code
1
2 3 |
public void AddValues(int d, int b) {
c = a + b; } |
再次运行编译,可以看到报告了如下错误:
更改回去,继续下面的测试。
测试自定义脚本
在外部创建脚本文件 MyBehaviour.cs,代码如下:
编译脚本里,将这个文件也加入编译,代码更改为:
C# Code
1
2 3 4 5 6 7 8 9 10 11 12 |
using UnityEngine;
namespace DLLTest { public class MyBehaviour : MonoBehaviour { void Start() { Debug.Log("MyBehaviour"); } } } |
C# Code
1
|
string[] sources = new[] {Path.Combine(srcPath, "MyUtilities.cs"), Path.Combine(srcPath, "MyBehaviour.cs") };
|
那么将引用到的 DLL 文件路径也加入进去,更改编译脚本的代码,更改为:
C# Code
1
|
string[] references = new []{ Path.Combine(EditorApplication.applicationContentsPath, "Managed/UnityEngine.dll") };
|
再次运行编译,可以看到不再报错,挂载 MyBehaviour 脚本到物体上,运行,可以看到日志输出如下:
测试 Mac平台
可以看到在 Mac 平台也是支持编译外部 DLL,并且也会自动生成 mdb文件。