提问人:MrBott_a 提问时间:11/14/2023 最后编辑:MorionMrBott_a 更新时间:11/15/2023 访问量:62
有没有办法在 Unity 中使用 Roslyn?
Is there a way to use Roslyn in Unity?
问:
所以,我有了一个项目,我们将称之为 X。 X 是用 .NET Core 3.1 开发的控制台应用程序,我想给这个应用程序一个与 Unity 的接口。 此应用程序的核心部分是基于某些文本的代码的动态生成。在 X 中,我使用 Roslyn 来做到这一点。我已经通过NuGet安装了Microsoft.CodeAnlysis.CSharp.Scripting包以及它携带的所有包,并且效果很好。 在Unity中“转换”项目(在播放器设置中设置为针对.NET Framework进行编译)我做了我最努力的事情。我将 X 文件夹中的所有脚本复制并粘贴到 Unity Asset 文件夹中,然后开始重写需要重写的内容。一切都很顺利,直到我进入代码生成部分。经过一番喧嚣,我发现了 NuGetForUnity,我用它来获取与最新版本的 X 中使用的相同的 NuGet 包。安装完所有内容后,我尝试运行我的应用程序。我收到这个错误:
> System.NotImplementedException: The method or operation is not implemented.
at System.Runtime.Loader.AssemblyLoadContext.LoadFromStream (System.IO.Stream assembly, System.IO.Stream assemblySymbols) [0x00000] in <b903c2b7b82245b2878c8afa0d6b7576>:0
at Microsoft.CodeAnalysis.Scripting.Hosting.CoreAssemblyLoaderImpl.LoadFromStream (System.IO.Stream peStream, System.IO.Stream pdbStream) [0x00000] in <7da58dd2a6fc48459bcdbf30dedfadbc>:0
at Microsoft.CodeAnalysis.Scripting.Hosting.InteractiveAssemblyLoader.LoadAssemblyFromStream (System.IO.Stream peStream, System.IO.Stream pdbStream) [0x00000] in <7da58dd2a6fc48459bcdbf30dedfadbc>:0
at Microsoft.CodeAnalysis.Scripting.ScriptBuilder.Build[T] (Microsoft.CodeAnalysis.Compilation compilation, Microsoft.CodeAnalysis.DiagnosticBag diagnostics, System.Boolean emitDebugInformation, System.Threading.CancellationToken cancellationToken) [0x000c6] in <7da58dd2a6fc48459bcdbf30dedfadbc>:0
at Microsoft.CodeAnalysis.Scripting.ScriptBuilder.CreateExecutor[T] (Microsoft.CodeAnalysis.Scripting.ScriptCompiler compiler, Microsoft.CodeAnalysis.Compilation compilation, System.Boolean emitDebugInformation, System.Threading.CancellationToken cancellationToken) [0x00026] in <7da58dd2a6fc48459bcdbf30dedfadbc>:0
at Microsoft.CodeAnalysis.Scripting.Script`1[T].GetExecutor (System.Threading.CancellationToken cancellationToken) [0x0002b] in <7da58dd2a6fc48459bcdbf30dedfadbc>:0
at Microsoft.CodeAnalysis.Scripting.Script`1[T].CreateDelegate (System.Threading.CancellationToken cancellationToken) [0x0000d] in <7da58dd2a6fc48459bcdbf30dedfadbc>:0
at CodeGenerator.GenericExternalBuilder[T] (System.Collections.Concurrent.ConcurrentDictionary`2[TKey,TValue] coll) [0x008c2] in C:\Users\User\Documents\uXCOM\Assets\Scripts\CodeGenerator.cs:198
at (wrapper dynamic-method) System.Object.CallSite.Target(System.Runtime.CompilerServices.Closure,System.Runtime.CompilerServices.CallSite,System.Type,object)
at System.Dynamic.UpdateDelegates.UpdateAndExecuteVoid2[T0,T1] (System.Runtime.CompilerServices.CallSite site, T0 arg0, T1 arg1) [0x00113] in <dab7f68612224ba3ae40f651d44f9d4c>:0
at CodeGenerator.InitializeAllExternals () [0x00026] in C:\Users\User\Documents\uXCOM\Assets\Scripts\CodeGenerator.cs:52
UnityEngine.Debug:LogError (object)
XCOM.XLogger:FixedUpdate () (at Assets/Scripts/XLogger.cs:100)
真正困扰我的是主要异常是 NotImplementedException。我的第一个困难是最新版本不是一个稳定的版本,所以我通过 NuGetForUnity 降级,但抛出了另一个异常(我没有它,但如果有用,我会提供它)。在那之后,我尝试了我能想到的一切:降级到我在 X 中使用的版本,通过 .unitypackage 安装相同的包,不同版本的包,在播放器设置中将编译器版本切换到 .NET Standard 2.1,但没有任何效果。 我将留下一段引发相同异常的代码,以便在您的项目中重现:
private void Test()
{
string code = "{ int a = 1; int b = 3; return a + b; }";
ScriptRunner<int> script = CSharpScript.Create<int>(code).CreateDelegate();
Debug.Log(script.Invoke());
}
这会引发相同类型的异常,只是略有不同:
> NotImplementedException: The method or operation is not implemented.
System.Runtime.Loader.AssemblyLoadContext.LoadFromStream (System.IO.Stream assembly, System.IO.Stream assemblySymbols) (at <b903c2b7b82245b2878c8afa0d6b7576>:0)
Microsoft.CodeAnalysis.Scripting.Hosting.CoreAssemblyLoaderImpl.LoadFromStream (System.IO.Stream peStream, System.IO.Stream pdbStream) (at <7da58dd2a6fc48459bcdbf30dedfadbc>:0)
Microsoft.CodeAnalysis.Scripting.Hosting.InteractiveAssemblyLoader.LoadAssemblyFromStream (System.IO.Stream peStream, System.IO.Stream pdbStream) (at <7da58dd2a6fc48459bcdbf30dedfadbc>:0)
Microsoft.CodeAnalysis.Scripting.ScriptBuilder.Build[T] (Microsoft.CodeAnalysis.Compilation compilation, Microsoft.CodeAnalysis.DiagnosticBag diagnostics, System.Boolean emitDebugInformation, System.Threading.CancellationToken cancellationToken) (at <7da58dd2a6fc48459bcdbf30dedfadbc>:0)
Microsoft.CodeAnalysis.Scripting.ScriptBuilder.CreateExecutor[T] (Microsoft.CodeAnalysis.Scripting.ScriptCompiler compiler, Microsoft.CodeAnalysis.Compilation compilation, System.Boolean emitDebugInformation, System.Threading.CancellationToken cancellationToken) (at <7da58dd2a6fc48459bcdbf30dedfadbc>:0)
Microsoft.CodeAnalysis.Scripting.Script`1[T].GetExecutor (System.Threading.CancellationToken cancellationToken) (at <7da58dd2a6fc48459bcdbf30dedfadbc>:0)
Microsoft.CodeAnalysis.Scripting.Script`1[T].CreateDelegate (System.Threading.CancellationToken cancellationToken) (at <7da58dd2a6fc48459bcdbf30dedfadbc>:0)
MainScript.Test () (at Assets/Scripts/MainScript.cs:33)
MainScript.Start () (at Assets/Scripts/MainScript.cs:22)
我希望它做的是在编辑器控制台 4 上打印。
答:
几年前我和你做了同样的事情。我使用 API(class CSharpCodeProvider 和 class CompilerParameters)来做到这一点。我认为你可以尝试一下。
我在 2022 年 8 月这样做了,也许现在更容易了。但这些帮助我让它工作:
您可能需要几周时间才能使其正常工作。
如果你的目标是IL2CPP,你需要查看 https://github.com/scottyboy805/dotnow-interpreter/wiki/Roslyn-C%23-Integration
另外,Unity Asset Store 中有 Roslyn C#(可能在 24 小时内发售)——利用它将把时间缩短一半。您可能想要查看 https://forum.unity.com/threads/released-roslyn-c-runtime-c-compiler.651505/page-5#post-8102249
有大量的极端情况(例如“是否要在脚本中利用 Newtonsoft.Json”)会根据您的需要增加额外的挑战。
评论