Skip to content

common_errors

walon edited this page May 27, 2022 · 12 revisions

常见错误

遇到 MissingMethodException xxx 错误

如果未出现AOT generic method的字眼,则这是unity代码裁剪引起的函数丢失,你使用常规的避免unity代码裁剪的方式处理即可。

常规两种做法

  • 在link.xml preserve这个函数。
  • 主工程中显式带上类或者函数的使用,如huatuo_trial中Assets/Main/HuatuoLib/RefTypes.cs所做的那样。

遇到 Unity: TypeLoadException xxx 错误

同样是unity代码裁剪引用的类型缺失。处理方法同上。

遇到 MissingMethodException: AOT generic method isn't instantiated in aot module xxx 错误

这是因为AOT泛型函数实例化缺失引起的,请 ===一定要=== 先详细看一下 AOT泛型限制及原理介绍 文档。

解决办法为:错误日志告诉你缺失哪个AOT函数实例化,你就在主工程里加上对这个函数的调用,使得il2cpp在打包时能生成这个泛型函数的代码。 主工程里任意地方加个这个泛型AOT函数调用都可以,目前一般集中加到 RefTypes.cs 这个文件里。

如果是async相关代码发生这种错误(具体见下面的示例5),则是因为编译器为async生成了若干类及状态机及一些代码,这些隐藏生成的代码中包含了对AOT泛型函数(如示例5中void System.Runtime.CompilerService.AsyncVoidMethodBuilder::Start<T>(ref T)) 的调用。用常规的AOT泛型的解决办法处理它即可。但有时候,你添加了void System.Runtime.CompilerService.AsyncVoidMethodBuilder::Start<StateMachine>(StateMachine&)的泛型实例化,理论上能泛型共享却仍然报错,则原因是你的dll使用了release编译模式,编译async时生成了值类型的状态机(也就是示例中的UIMgr+ShowUId__2是值类型),而值类型是无法泛型共享的。具体情况有两种:

  • 如果你的热更新dll直接拷贝自Library/ScriptAssemblies目录。解决办法为在Unity Editor窗口最下面的状态栏,有一个臭虫按钮可以切换 Debug/Release,切换成Debug,并且 ==务必== 清除你的Library/ScriptAssemblies目录及已经打包好的dll。
  • 如果你的热更新dll使用了类似huatuo_trial项目的HuatuoEditorHelper里编译代码编译出的dll。则因为你少加了scriptCompilationSettings.options = ScriptCompilationOptions.DevelopmentBuild;,导致编译出的dll是release模式。

示例1

错误日志

MissingMethodException: AOT generic method isn't instantiated in aot module System.Collections.Generic.IEnumerable'1[[System.Byte,mscorlib,Version=4.0.0.0,Culture=neutral,PublicKeyToken=b77a5c561934e089]] System.Linq.Enumerable::Skip<System.Byte>(System.Collections.Generic.IEnumerable'1[[System.Byte,mscorlib,Version=4.0.0.0,Culture=neutral,PublicKeyToken=b77a5c561934e089],System.Init32)

你在RefType里加上 IEnumerable.Skip<byte>(IEnumerable<byte>, int)的调用。

class RefTypes
{

  public void MyAOTRefs()
  {
      IEnumerable.Skip<byte>((IEnumerable<byte>)null, 0);
  }
}

示例2

错误日志

MissingMethodException: AOT generic method isn't instantiated in aot module void System.Collections.Generic.List<System.String>.ctor()

你在RefType里加上 List<string>.ctor() 的调用,即 new List<string>()。由于泛型共享机制,你调用 new List<object>() 即可。

class RefTypes
{

  public void MyAOTRefs()
  {
      new List<object>();
  }
}

示例3

错误日志

MissingMethodException: AOT generic method isn't instantiated in aot module void System.ValueType<System.Int32, System.String>.ctor()

注意!值类型的空构造函数没有调用相应的构造函数,而是对应 initobj指令。实际上你无法直接引用它,但你只要强制实例化这个类型就行了,preserve这个类的所有函数,自然就会包含.ctor函数了。

实际中你可以用强制装箱 (object)(default(ValueTuple<int, object>))。

class RefTypes
{

  public void MyAOTRefs()
  {
      // 以下两种写法都是可以的
      _ = (object)(new ValueTuple<int, object>());
      _ = (object)(default(ValueTuple<int, object>));
  }
}

示例4

错误日志

MissingMethodException: AOT generic method isn't instantiated in aot module void YourGenericClass<System.Int32, List<string>>.Show<List<int>, int>(List<string>, ValueTuple<int, string>, int)
class RefTypes
{

  public void MyAOTRefs()
  {
      YourGenericClass<int, object>.Show<object,int>(default(object), default(ValueTuple<int,object>), default(int));
  }
}

示例5

错误日志

  MissingMethodException: AOT generic method isn't instantiated in aot module System.Void System.Runtime.CompilerService.AsyncVoidMethodBuilder::Start<UIMgr+ShowUId__2>(UIMgr+<ShowUI>d__2)
class RefTypes
{

  public void MyAOTRefs()
  {
      var builder = new System.Runtime.CompilerService.AsyncVoidMethodBuilder();
      builder.Start(default(IAsyncStateMachine));
  }
}

遇到 ExecutionEngineException: GetManaged2NativeMethodPointer not support. xxxx 函数名

这是因为这个AOT函数与interpreter之间的桥接函数不存在。请参考 桥接函数 文档进行处理。

遇到 "This icall is not supported by il2cpp at System.AppDomain.Load"

有两种原因

  1. 如果非ios平台,则因为未替换libil2cpp目录
  2. 如果ios平台,因为ios平台并不从源码编译libil2cpp,而是使用随Editor打包的libil2cpp.a,你需要替换libil2cpp.a为huatuo的编译版本。编译方式请看IOS Build

打包时遇到 static_assert(sizeof(il2cpp_array_size_t) == 8, "array size type == 8") 的错误

因为你build了32位程序。 huatuo当前只支持64位,将来才会支持32位。

如果你正在打包android,请去掉armv7的target。

打包时遇到 only support 64bit 的错误

原因同上。

遇到 Unity: TypeLoadException: Could not load type 'System.Object' from assembly 'netstandard'

目前支持.net standard 2.0,但要求主工程打包用.net standard,而热更新dll打包必须用.net 4.x。原因是unity使用.net standard打包时,会自动剥除.net standard的依赖,直接依赖最终的dll,导致主工程的dll列表中实际上不存在net standard这个dll,进而导致热更新dll加载时,找不到来自netstandard的对象。

解决办法为编译热更新部分时api compatible level切换为.net 4.x或 .net framework即可。

如果使用了第三方dll形式的插件,并且插件只支持.net standard。将插件放到主工程也能正常工作,但不能放到热更新部分。对依赖.net 4.x的插件则无限制,都能正常工作。

如果还发生错误,则删除Library目录,重新操作一次。

热更新dll也使用.net standard打包也是有办法正常工作的。需要在加载热更新dll前先手动加载.net standard dll,但这导致增加无谓的空间和内存占用,因此不建议这么操作。况且huatuo目前还不支持export type特性,实际上仍然是不能工作的。

打包生成Visual Studio Project后,编译出现错误找不到Windows SDK版本或无法打开.....\binUnityPlayerStub.lib

打包生成的C++工程中,依赖关系为:项目主工程(同unity项目名,当前启动项目)依赖Il2CppOutputProject,Il2CppOutputProject依赖UnityPlayerStub。但是生成的工程设置中并没有设置依赖,一般按照下面的设置就能解决:

  1. 编译UnityPlayerStub项目,遇到问题就修改项目设置里面的 Windows SDK Version 和 Platform Toolset
  2. 编译Il2CppOutputProject 项目
  3. 启动成功