Unity 打包il2cpp模式时的常见问题分析
由于Android/iOS不同的版本对编译器(NDK/xcode)的版本要求也是不同的,而大多数同学下载的NDK/xcode 是网络上的一个版本,不一定匹配上unity 编译Android/iOS时对应的版本,所以如果在发布il2cpp模式过程中,当我们遇到编译错误的时候,首先先编译空项目,看看是不是NDK,SDK,xcode的版本不匹配导致的。Unity 编辑器模式下是采用.net 虚拟机解释执
Unity 编辑器模式下是采用.net 虚拟机解释执行.net 代码,发布的时候有两种模式,一种是mono虚拟机模式,一种是il2cpp模式。
由于iOS AppStore规定不允许使用虚拟机,所以发布到iOS,Unity采用了il2cpp技术,把IL(.net字节码) 的代码转成c++代码,然后再用xcode来进行编译。
发布到Android的时候,可以用mono与il2cpp模式,il2cpp由于转成native code直接在硬件CPU上跑,性能要比虚拟机解释执行要高,所以发布Android的时候我们也采用il2cpp。
但是开发者会遇到一些问题mono模式下能正常运行,编译il2cpp模式下会出现问题,如闪退等,本文将il2cpp 打包发布可能遇到的问题,进行分类,分析与总结,希望能给大家提供解决思路与方向。
il2cpp模式编译错误
首先遇到的问题是使用il2cpp模式下编译C++代码报错。由于Android/iOS不同的版本对编译器(NDK/xcode)的版本要求也是不同的,而大多数同学下载的NDK/xcode 是网络上的一个版本,不一定匹配上unity 编译Android/iOS时对应的版本,所以如果在发布il2cpp模式过程中,当我们遇到编译错误的时候,首先先编译空项目,看看是不是NDK,SDK,xcode的版本不匹配导致的。
Unity Hub 现在也集成了一个功能就是安装对应Unity版本对应的NDK与SDK。安装正确的工具链编译问题一般能很轻松的解决。(如下图所示, Unity hub中不同unity版本,安装相关编译工具时的模块化安装)
Mono模式下没问题, il2cpp模式下报类型缺失错误
开发完打包的时候,mono模式下没有问题, il2cpp模式下编译通过,但是运行的时候报”类型缺失的错误”。这也是常见的il2cpp模式下遇到的问题。C++是属于根据依赖进行编译的模式。Il2cpp中,如果我们编写的c#代码没有使用这个类,那么编译完C++代码后,这个类的二进制代码就不会出现在c++的代码中,运行的时候就会导致类型缺失,功能不正常等相关报错。
很多同学看到这里就有一个疑问,既然IL的.dll代码里面没有,为何C++的代码会调用呢?给大家举个例子你瞬间就明白了,假设有个资源预制体挂了一个组件,而这个组件只在资源上使用,代码中没有使用,编辑器模式下与mono模式下都能正常运行。而打包il2cpp的时候由于这个组件在代码中没有使用, 所以导致IL code中没有依赖,因此就不会被il2cpp打入进去,导致l2cpp模式下运行的时候类型缺失报错,功能不能正常使用。
了解了出错的原因与原理,解决方案就非常简单在ilcode代码里面加上组件类的代码引用与依赖就可以了,让il2cpp将相关的类与组件打入进去。比如动画的timeline等。
Mono模式没有问题,IL2CPP模式下闪退
最后一类问题就是mono模式下没有问题,il2cpp模式下闪退。闪退其实就是手机app的这个进程由于运行时候的错误,OS必须要杀掉这个进程,而虚拟机解释执行式模式,不容易闪退,因为有虚拟机这一层作为保护隔绝,而对于il2cpp而言,全部已经转成了native 代码,如果运行的时候数据不对,比如除0异常,空指针等会导致OS 直接把进程删掉造成闪退。所以这样就会导致mono模式下不闪退,而il2cpp模式下却直接闪退。
引起这类问题原因有很多,比如上面的类型缺失,可能导致闪退, 还有就是某个代码与数据跑出来缺失异常了,但是mono下由于有虚拟机的保护作用,异常可能被直接忽视了,导致我们认为还在app正常运行,而il2cpp模式下由于没有虚拟机的保护,可能直接被OS 杀掉。
一般解决这类我们问题我们还是要通过隔离的手段,找出运行出错的代码与相关数据,然后分析原因来修正它。而不要老想着 “mono正常,而il2cpp模式下报错,闪退”是不是il2cpp的环境问题。其实很大一部分确实是我们的代码或我们代码跑的数据异常导致的。
更多推荐
所有评论(0)