ILRuntime热更案例学习(五) ------ 注意事项总结

ILRuntime热更案例学习(五) ------ 注意事项总结

官方示例下载地址1: https://github.com/Ourpalm/ILRuntime

官方示例下载地址2 : https://github.com/Ourpalm/ILRuntimeU3D

官方文档地址 : https://ourpalm.github.io/ILRuntime/public/v1/guide/tutorial.html


一.iOS IL2CPP打包注意事项

1.类型裁剪

IL2CPP在打包时会自动对Unity工程的DLL进行裁剪,将代码中没有引用到的类型裁剪掉,以达到减小发布后ipa包的尺寸的目的。然而在实际使用过程中,很多类型有可能会被意外剪裁掉,造成运行时抛出找不到某个类型的异常。特别是通过反射等方式在编译时无法得知的函数调用,在运行时都很有可能遇到问题。

在Unity工程的Assets目录中建立一个叫link.xml的XML文件,然后按照下面的格式指定你需要保留的类型:

<linker>
  <assembly fullname="UnityEngine" preserve="all"/>
  <assembly fullname="Assembly-CSharp">
    <namespace fullname="MyGame.Utils" preserve="all"/>
    <type fullname="MyGame.SomeClass" preserve="all"/>
  </assembly>  
</linker>

2.泛型实例

每个泛型实例实际上都是一个独立的类型,List<A>List<B>是两个完全没有关系的类型,这意味着,如果在运行时无法通过JIT来创建新类型的话,代码中没有直接使用过的泛型实例都会在运行时出现问题。

在ILRuntime中解决这个问题有两种方式,一个是使用CLR绑定,把用到的泛型实例都进行CLR绑定。另外一个方式是在Unity主工程中,建立一个类,然后在里面定义用到的那些泛型实例的public变量。这两种方式都可以告诉IL2CPP保留这个类型的代码供运行中使用。

因此建议大家在实际开发中,尽量使用热更DLL内部的类作为泛型参数,因为DLL内部的类型都是ILTypeInstance,只需处理一个就行了。此外如果泛型模版类就是在DLL里定义的的话,那就完全不需要进行任何处理。

3.泛型方法

跟泛型实例一样,foo.Bar<TypeA>foo.Bar<TypeB>是两个完全不同的方法,需要在主工程中显式调用过,IL2CPP才能够完整保留,因此需要尽量避免在热更DLL中调用Unity主工程的泛型方法。如果在iOS上实际运行遇到报错,可以尝试在Unity的主工程中随便写一个static的方法,然后对这个泛型方法调用一下即可,这个方法无需被调用,只是用来告诉IL2CPP我们需要这个方法

二.开发注意事项

热更部分的代码都不继承MonoBehaviour,也就是都不挂脚本,非热更部分随意:热更对MonoBehaviour这种比较特殊东西的支持都挺麻烦,要么不用,要么只是做个不可热更的消息转发层;要么开发时挂脚本,打包时用某种特殊的方式把它变成代码里动态AddComponent。

尽量不要跨域调用啥的

三.热更方式选择

1. Android
不用任何第三方的热更方案,用C#反射执行DLL,性能和代码写法和纯C#基本一样。
Google Pay强制要求在2019年8月之前App都支持64位,Unity的应对方案是Android IL2cpp,暂时没有支持mono backend 64位的打算。所以到时候只能是IL2CPP + ILRuntime的方式,性能会差一大截,主要慢在ILRuntime上。

不过现在年底了,博主打算不考虑iOS和Android的区分了~~~

2. iOS
ILRuntime + DLL 解释执行,当然是在IL2CPP下。