Unity 版本 5.6.6f2

在使用 Android 的 IL2CPP 时,发生编译报错,报错内容如下所示:

Unity Android IL2CPP 编译报错的一种可能原因_ios

Unity Android IL2CPP 编译报错的一种可能原因_Unity_02

stdout:
IL2CPP error (no further information about what managed code was being converted is available)
Additional information: Build a development build for more information. δ�������������õ�������ʵ����
il2cpp.exe didn't catch exception: System.NullReferenceException: δ�������������õ�������ʵ����
   �� Unity.IL2CPP.Extensions.GetBaseType(TypeReference typeReference)
   �� Unity.IL2CPP.GenericSharing.GenericSharingVisitor.AddStaticUsageRecursiveIfNeeded(TypeReference genericType)
   �� Unity.IL2CPP.GenericSharing.GenericSharingVisitor.Process(Instruction instruction, MethodDefinition method)
   �� Unity.IL2CPP.GenericSharing.GenericSharingVisitor.ProcessType(TypeDefinition type)
   �� Unity.IL2CPP.GenericSharing.GenericSharingVisitor.Collect(AssemblyDefinition assembly)
   �� Unity.IL2CPP.AssemblyConverter.PreProcessStage(IInteropDataCollector interopDataCollector, ReadOnlyInflatedCollectionCollector& readOnlyGenericsCollectionCollector, TypeDefinition[]& allTypeDefinitions)
   �� Unity.IL2CPP.AssemblyConverter.Apply()
   �� Unity.IL2CPP.AssemblyConverter.ConvertAssemblies(NPath[] assemblies, NPath outputDir, NPath dataFolder, NPath symbolsFolder)
   �� Unity.IL2CPP.AssemblyConverter.ConvertAssemblies(IEnumerable`1 assemblyDirectories, IEnumerable`1 explicitAssemblies, NPath outputDir, NPath dataFolder, NPath symbolsFolder)
   �� il2cpp.Program.DoRun(String[] args)
   �� il2cpp.Program.Run(String[] args)
   �� il2cpp.Program.Main(String[] args)
stderr:

δ���������쳣:  System.NullReferenceException: δ�������������õ�������ʵ����
   �� Unity.IL2CPP.Extensions.GetBaseType(TypeReference typeReference)
   �� Unity.IL2CPP.GenericSharing.GenericSharingVisitor.AddStaticUsageRecursiveIfNeeded(TypeReference genericType)
   �� Unity.IL2CPP.GenericSharing.GenericSharingVisitor.Process(Instruction instruction, MethodDefinition method)
   �� Unity.IL2CPP.GenericSharing.GenericSharingVisitor.ProcessType(TypeDefinition type)
   �� Unity.IL2CPP.GenericSharing.GenericSharingVisitor.Collect(AssemblyDefinition assembly)
   �� Unity.IL2CPP.AssemblyConverter.PreProcessStage(IInteropDataCollector interopDataCollector, ReadOnlyInflatedCollectionCollector& readOnlyGenericsCollectionCollector, TypeDefinition[]& allTypeDefinitions)
   �� Unity.IL2CPP.AssemblyConverter.Apply()
   �� Unity.IL2CPP.AssemblyConverter.ConvertAssemblies(NPath[] assemblies, NPath outputDir, NPath dataFolder, NPath symbolsFolder)
   �� Unity.IL2CPP.AssemblyConverter.ConvertAssemblies(IEnumerable`1 assemblyDirectories, IEnumerable`1 explicitAssemblies, NPath outputDir, NPath dataFolder, NPath symbolsFolder)
   �� il2cpp.Program.DoRun(String[] args)
   �� il2cpp.Program.Run(String[] args)
   �� il2cpp.Program.Main(String[] args)

UnityEngine.Debug:LogError(Object)
UnityEditorInternal.Runner:RunManagedProgram(String, String, String, CompilerOutputParserBase, Action`1) (at C:/buildslave/unity/build/Editor/Mono/BuildPipeline/BuildUtils.cs:96)
UnityEditorInternal.IL2CPPBuilder:RunIl2CppWithArguments(List`1, Action`1, String) (at C:/buildslave/unity/build/Editor/Mono/BuildPipeline/Il2Cpp/IL2CPPUtils.cs:313)
UnityEditorInternal.IL2CPPBuilder:ConvertPlayerDlltoCpp(ICollection`1, String, String) (at C:/buildslave/unity/build/Editor/Mono/BuildPipeline/Il2Cpp/IL2CPPUtils.cs:304)
UnityEditorInternal.IL2CPPBuilder:Run() (at C:/buildslave/unity/build/Editor/Mono/BuildPipeline/Il2Cpp/IL2CPPUtils.cs:151)
UnityEditorInternal.IL2CPPUtils:RunIl2Cpp(String, String, IIl2CppPlatformProvider, Action`1, RuntimeClassRegistry, Boolean) (at C:/buildslave/unity/build/Editor/Mono/BuildPipeline/Il2Cpp/IL2CPPUtils.cs:34)
UnityEditor.HostView:OnGUI()

从报错信息来看,是空引用异常,但是却没有指明错误的具体位置。另外,通过其他工程测试 IL2CPP 编译是正常的,说明是当前工程的代码有问题。通过排除法来定位具体错误的位置,最终定位到代码里有一个方法,如下:

static bool IsIosDeviceHighEnd()
{
    string generation = UnityEngine.iOS.Device.generation.ToString().ToLower();
    return list.Contains(generation);
}


虽然在 Android 下不会调用这个方法,但还是进行编译了,而 UnityEngine.iOS.Device 是 iOS 系统的特殊功能接口,在 Android 的 IL2CPP 并没有对应的 C++ 实现,所以就编译错误了。

这里可以通过加宏来控制编译,如下

#if UNITY_IOS
static bool IsIosDeviceHighEnd()
{
    string generation = UnityEngine.iOS.Device.generation.ToString().ToLower();
    return list.Contains(generation);
}
#endif

之后如果再遇到 IL2CPP 编译错误,可以检查下是否包含了 Android 平台下没有实现的方法接口之类的。