码迷,mamicode.com
首页 > 编程语言 > 详细

Unity3D的IL2CPP平台找不到默认构造函数的坑

时间:2015-10-09 22:47:58      阅读:990      评论:0      收藏:0      [点我收藏+]

标签:

         最初发现这个问题的情况是,当游戏用IL2CPP平台发布IOS版本的时候,会遇到某些dll格式的插件会导致游戏抛异常崩溃,比如FullInspector和Behavior Designer。所抛的异常是找不到某些类的默认构造函数。

         后来发现,不只是某些插件会报这种异常,很多json格式的序列化功能也会在IL2CPP平台上抛找不到默认构造函数的异常。

         导致这个问题的原因是,IL2CPP版本在AOT编译时的一些优化机制导致的。想要详细了解这个机制的话可以看文档:http://docs.unity3d.com/Manual/iphone-playerSizeOptimization.html

         其实问题就出在函数的静态调用和利用反射进行动态调用的区别上。在AOT阶段编译的时候,凡是检查到某个类或某个函数完全没有使用到,编译器就会抛弃它。这是一个优化机制,但问题就是这种检查只能检查静态引用,对于利用反射机制进行的调用编译器发现不了。这就导致了,没有进行静态引用的函数,会被编译器抛弃掉,然后在企图通过反射机制进行调用的时候,就会导致找不到要调用的函数。

         举个例子,有些序列化插件,比如FullSerializer,在生成新对象的时候没有用new(静态引用),而是用了Activator泛型(动态反射)。所以类的构造函数会在编译的时候抛弃掉,然后Activator企图动态访问其动态函数的时候,问题就出现了。

         解决这个问题的方法,比较直接的做法在代码中加入丢失的构造函数的静态引用,也就是随便找个地方new一个出来。这样可以防止IL2CPP在优化的时候被抛弃。这种做法的问题是会留一个无用的对象在内存里。

         更好的做法是用Unity3D的link.xml功能。这个link.xml的功能就是在AOT编译的时候,告诉编译器,link.xml里指定的这些类,不管有没有引用到,都要保留下来。虽然可以精确指向到某个类,但是比较简单的做法是,把整个出问题的插件的命名空间全部包含进去就可以了。

         举个例子,在对应FullInspector和Behavior Designer的时候,link.xml大概是长这个样子的:

<linker>

       <assembly fullname="FullInspector-Core">

               <namespace fullname="FullInspector" preserve="all"/>

       </assembly>

 

       <assembly fullname="BehaviorDesignerRuntime">

               < namespace fullname="BehaviorDesigner.Runtime " preserve="all"/>

       </assembly>

</linker>

         这样这两个插件里的类和函数都会被完整的保留下来了,问题解决。

Unity3D的IL2CPP平台找不到默认构造函数的坑

标签:

原文地址:http://www.cnblogs.com/rockgong/p/4865243.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!