gpt4 book ai didi

c# - 如何在编译后更改 AssemblyName 以在 Unity3d 中作为 mod 加载

转载 作者:太空狗 更新时间:2023-10-29 21:49:53 24 4
gpt4 key购买 nike

我一直在研究向 Unity3D 游戏添加模组支持。我是 Unity 的新手(但不是 .NET),所以如果我似乎遗漏了一些明显的东西,请告诉我,因为我可能是。

我希望能够直接从编辑器导出对象,包括自定义脚本。获取与脚本关联的程序集非常容易。项目中任何松散的脚本似乎都被编译为 Assembly-CSharp.dll。当我尝试在运行时在另一个 Unity 项目中加载程序集时出现问题。调用 Assembly.Load(byte[]) 返回给我当前项目的程序集,而不是字节数组表示的程序集。我假设这是因为来自 mod 项目和宿主项目的程序集的 AssemblyName 都是相同的(Assembly-CSharpVersion=0.0.0.0, Culture=neutral, PublicKeyToken=null).

作为测试,我为 mod 项目更新了我的 Visual Studio 项目,将其从 Assembly-CSharp 重命名为不同的名称。这被 Unity 消除了,但我可以在此之前进行构建,并使用 Assembly-CSharp 以外的名称获取我正在寻找的程序集。通过 Assembly.Load(byte[]) 加载它似乎可以在非常简单的“导入脚本以旋转多维数据集”这种场景中发挥作用。虽然这看起来可行,但我真的想从 Unity 编辑器中寻找更自动、神奇的单步操作。

现在,回到问题...

如果我理解这个问题,我正在寻找一种在编译后更改程序集的 AssemblyName 的编程方式。欢迎所有建议和建议。

我调查或考虑过的一些可能的路线:

1) 一种神奇的 API 方法,用于更改 AssemblyName 并保存它。这将是理想的,但我还没有在这里偶然发现任何有用的东西。

2) 编辑程序集的原始字节以更改名称? 不确定这是否可能,但如果我可以安全可靠地覆盖程序集的一些原始字节以更改其名称, 那会膨胀。

3) 创建一个包含原始程序集中类型的新动态程序集。 我对动态程序集的经验有限。我可以创建一个,但我不确定如何(如果可能)将原始程序集中定义的类型复制到新的动态程序集中。

4) 使用 CSharpCodeProvider 手动编译程序集。 假设 Unity 支持它,那么我认为这可能会奏效,虽然看起来很痛苦。我还没有研究如何找到编译所需的所有脚本和引用。如果可能的话,我想避免它。

5) *ilasm/ildasm 的一些魔法。* 假设有 unity 等价物..这些工具可以做到这一点吗?

6) 以编程方式更新 csproj 文件并重新编译。 看起来很笨拙而且很痛苦。我想我需要有代码来支持 Visual Studio 和 MonoDevelop。

我宁愿避免使用外部工具和重新编译,所以前三个选项之一是理想的。想法、想法?谢谢!


奖金问题:我的“导入脚本以旋转立方体”测试似乎有效,但是在加载程序集期间的日志中,我看到下面的两条消息。那不是我使用的程序集名称,不确定它来自哪里。我应该担心吗?这以后还会回来咬我吗?

> Non platform assembly: data-0B9D7940 (this message is harmless)
> Fallback handler could not load library C:/Dev/Test
> Projects/ModTest/Build/ModHost1/ModHost1_Data/Mono/data-0B9D7940.dll

最佳答案

我最终采用的解决方案是使用 Mono.Cecil。幸运的是,Mono.Cecil 库在 Unity 编辑器中可用,无需使用我的 mod 工具部署任何额外的库。 Mono.Cecil 非常适合在编译后重命名程序集。这是我用来实现它的一些代码:

     // Have Mono.Cecil load the assembly
var assemblyDefinition = Mono.Cecil.AssemblyDefinition.ReadAssembly(assemblyFile.FullName);

// Tell Mono.Cecil to actually change the name
assemblyDefinition.Name.Name = newAssemblyNameNoExtension;
assemblyDefinition.MainModule.Name = newAssemblyNameNoExtension;

// We also need to rename any references to project assemblies (first pass assemblies)
foreach (var reference in assemblyDefinition.MainModule.AssemblyReferences)
{
if (Utilities.IsProjectAssembly(reference.Name))
{
reference.Name = Utilities.GetModAssemblyName(reference.Name, this._modName);
}
}

// Build the new assembly
byte[] bytes;
using (var ms = new MemoryStream())
{
assemblyDefinition.Write(ms, new Mono.Cecil.WriterParameters() { WriteSymbols = true });
bytes = ms.ToArray();
}

关于c# - 如何在编译后更改 AssemblyName 以在 Unity3d 中作为 mod 加载,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28679003/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com