以前遊戲爲了解決在ios自動更新的問題,想到使用了將遊戲代碼打包成dll,使用反射加載執行的辦法。辦法想好了之後,一直沒有作測試。上週不知道什麼緣由,終於有人去測試了,結果發現報錯了。我當時以爲有點意外。雖然說網上有人說ios上不能使用.net的反射模塊,可是後來我仔細研究過這個問題,發現技術上應該是可行的。由於unity在使用C#做爲腳本時,底層是使用的是mono。而使用mono的話,在ios平臺上面,底層就應該是使用的Xamarin.iOS。它對於ios的限制主要在於它使用了AOT編譯,而不是傳統的JIT,也就是說IL代碼在編譯時,就被翻譯成對應平臺的機器碼,而不是如JIT同樣,在運行時動態翻譯。其實大部分嵌入式平臺都不會對JIT進行支持,主要是幾個方面緣由的考慮,(1)加快啓動程序時間;(2)執行效率;(3)節約內存。既然是使用AOT編譯,那麼它對反射的限制應該主要是限制部分依賴JIT的功能,所以這個問題得核心不是反射的問題,而是JIT與AOT區別的問題。而咱們使用反射只是在dll中查找一個已知類,這個應該是能夠靜態編譯的,對JIT沒有要求。ios
帶着疑問,我幫忙查看了下報錯的日誌。結果才發現不是加載dll的地方報錯了,而是在以後的代碼裏,protobuf-net的代碼。這個發現說明了兩個問題:(1)第一是dll裏的入口函數已經進入了,由於報錯的位置在這個以後很遠的地方。這說明了以前的思路是沒有問題。(2)第二protobuf-net在ios上面報錯的緣由仍是和前面說的AOT編譯限制有關。由於它使用了反射中對JIT有依賴的功能。函數
接下來就是解決protobuf-net的問題。其實以前早有人遇到了這個問題,protobuf-net做者所以提供了一個procompile的模塊來解決它。大概的思路是(1)將proto文件解析出來的cs文件編譯到一個獨立的dll中;(2)使用precompile模塊對這個新的dll進行處理,生成一個新的序列化dll,我我的以爲這個步驟主要是在這個序列化dll中記錄消息類的描述信息,以便後面序列化,反序列化時不須要對JIT依賴。(3)將生成的兩個dll,加上自己protobuf-net的dll一塊兒加入到遊戲工程,經過序列化dll裏的序列化方法對消息進行處理。測試
到這裏,這個問題應該就算解決了。不過感受步驟仍是有點繁瑣,這種機械化的工做就應該讓機器作,因此接下來就是將上面的幾個步驟,作成自動化批處理,每次編譯工程時,自動執行。這樣一來,也算完美解決了。spa