如何为System.Reflection调用的代码片段添加UnityEngine程序集引用
解决Unity运行时C#编译引用UnityEngine程序集的问题
核心问题根源
Unity的核心程序集(如UnityEngine.dll)在打包后的游戏中并非以普通文件形式存放在文件系统中,而是被嵌入到Unity的加载体系里。通过AppDomain.CurrentDomain.GetAssemblies()获取的Unity相关Assembly对象,其Location属性通常为空或指向无效路径,导致旧版编译器(如CSharpCodeProvider)无法找到对应的元数据文件,从而抛出CS0006错误。
可行解决方案
1. 动态获取程序集绝对路径(适配编辑器/打包环境)
针对旧版CSharpCodeProvider,需根据运行环境拼接UnityEngine.dll的绝对路径,添加到引用列表:
using System.IO; #if UNITY_EDITOR using UnityEditor; #endif // 构建UnityEngine.dll的绝对路径 string unityEnginePath; #if UNITY_EDITOR unityEnginePath = Path.Combine(EditorApplication.applicationContentsPath, "Managed", "UnityEngine.dll"); #else unityEnginePath = Path.Combine(Application.dataPath, "Managed", "UnityEngine.dll"); #endif // 添加到引用列表 references.Add(unityEnginePath);
此方法依赖文件系统中存在对应的DLL文件,在编辑器和标准打包环境下均有效。
2. 切换到Roslyn编译(推荐长期方案)
旧版CSharpCodeProvider功能受限,建议改用微软官方的Roslyn编译器(Microsoft.CodeAnalysis.CSharp),它支持直接引用内存中的程序集元数据,无需依赖文件路径:
- 在Unity项目中添加兼容的
Microsoft.CodeAnalysis.CSharp和Microsoft.CodeAnalysisNuGet包(选择适配.NET Framework 4.x的版本)。 - 替换编译逻辑为以下代码:
using System; using System.IO; using System.Linq; using System.Reflection; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp; // 构建程序集引用列表 var references = AppDomain.CurrentDomain.GetAssemblies() .Where(a => !a.IsDynamic && !string.IsNullOrEmpty(a.Location)) .Select(a => MetadataReference.CreateFromFile(a.Location)) .ToList(); // 单独处理UnityEngine等无有效路径的程序集 Assembly unityEngineAssembly = typeof(GameObject).Assembly; using (Stream stream = unityEngineAssembly.GetManifestResourceStream($"{unityEngineAssembly.GetName().Name}.dll")) { if (stream != null) { references.Add(MetadataReference.CreateFromStream(stream)); } } // 待编译代码示例 string code = @" using UnityEngine; public class RuntimeMod { public void Execute() { Debug.Log(""模组代码执行成功""); } }"; // 编译执行 var syntaxTree = CSharpSyntaxTree.ParseText(code); var compilation = CSharpCompilation.Create( "RuntimeModAssembly", syntaxTrees: new[] { syntaxTree }, references: references, options: new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary)); using (var ms = new MemoryStream()) { var emitResult = compilation.Emit(ms); if (emitResult.Success) { ms.Seek(0, SeekOrigin.Begin); Assembly modAssembly = Assembly.Load(ms.ToArray()); Type modType = modAssembly.GetType("RuntimeMod"); object modInstance = Activator.CreateInstance(modType); modType.GetMethod("Execute")?.Invoke(modInstance, null); } else { // 输出编译错误 foreach (var diagnostic in emitResult.Diagnostics) { UnityEngine.Debug.LogError(diagnostic.ToString()); } } }
常见错误规避
- 不要直接将"UnityEngine"添加到引用列表,编译器需要的是DLL的绝对路径或元数据,而非程序集名称。
- 打包后需确保游戏
Data/Managed目录下存在UnityEngine.dll(Unity默认会自动打包该文件)。
内容的提问来源于stack exchange,提问作者RiskOfAdventure
相关产品推荐
相关产品推荐

