如何为Microsoft.CodeAnalysis.CSharp.Scripting.CSharpScript指定目标框架为.NET Standard 2.1?
如何为Microsoft.CodeAnalysis.CSharp.Scripting.CSharpScript指定目标框架为.NET Standard 2.1?
你遇到的核心问题我太懂了——Roslyn脚本默认会以当前运行环境(你的.NET 9后端)的框架来编译,生成的程序集自然绑定.NET 9,而Unity通常基于.NET Standard 2.1,加载失败是必然的。直接替换或移除默认引用的思路容易踩坑(比如你遇到的基础类型缺失、类型转换错误),得用正确的编译配置来指定目标框架。
正确解决步骤
1. 先搞定编译用的参考程序集
你之前尝试的Basic.Reference.Assemblies.NetStandard21是完全正确的方向,这个包提供了官方的.NET Standard 2.1编译参考程序集,比直接用Unity的运行时程序集靠谱多了(运行时程序集带实现代码,不适合做编译参考)。先确保你已经安装了这个NuGet包。
2. 修改Compile方法,明确指定目标框架
不能只靠ScriptOptions设置引用,还得给编译过程指定目标框架和元数据版本。下面是调整后的完整方法:
using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp.Scripting; using Microsoft.CodeAnalysis.Scripting; using System.IO; using System.Linq; public (EmitResult result, byte[]? assemblyBytes) Compile(string code, string[] gameAssemblyPaths) { // 初始化脚本选项:先加.NET Standard 2.1的参考程序集,再追加Unity的程序集 var scriptOptions = ScriptOptions.Default .WithReferences(NetStandard21.References.All) .AddReferences(gameAssemblyPaths) .AddImports("System"); // 创建脚本并获取编译对象 var script = CSharpScript.Create(code, scriptOptions); var compilation = script.GetCompilation(); // 关键:修改编译选项,指定目标框架为.NET Standard 2.1 var csharpOptions = (CSharpCompilationOptions)compilation.Options; csharpOptions = csharpOptions .WithTargetFramework(TargetFramework.NetStandard21) .WithRuntimeMetadataVersion("v4.0.30319"); // 这个版本号是.NET Standard 2.1对应的标准元数据版本 // 更新编译对象的配置 compilation = compilation.WithOptions(csharpOptions); // 生成程序集 using var assemblyStream = new MemoryStream(); var emitResult = compilation.Emit(assemblyStream); return (emitResult, emitResult.Success ? assemblyStream.ToArray() : null); }
为什么之前的尝试会踩坑?
- 直接替换默认引用为Unity程序集:Unity的运行时程序集不是编译用的参考程序集,缺少基础类型的完整定义,所以会出现
System.Object未定义的错误。而且你手动移除System.Private.CoreLib后,连最基础的类型转换逻辑都找不到依赖了,自然报类型转换错误。 - 使用Basic.Reference.Assemblies但报错:大概率是你没配合修改编译的目标框架配置,只加了引用却没告诉编译器要编译到哪个框架,导致内部逻辑冲突抛出数组越界异常。
额外注意点
- 引用Unity的程序集时,尽量用Unity安装目录
Editor\Data\Managed下的参考程序集,而不是游戏打包后的运行时程序集。 - 如果遇到重复引用错误,可以在
AddReferences时加个.Distinct()去重。 - 编译失败时,一定要看
emitResult.Diagnostics里的具体错误信息,大概率是缺某个Unity程序集引用或者命名空间没导入。
内容来源于stack exchange
相关产品推荐
相关产品推荐

