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下。