朱峰社區(qū)首頁 朱峰社區(qū)

搜索資源 注冊|登陸

等待

返回 展開菜單

Unity3D將來時:IL2CPP(下)

face robot中文教程 觀看預覽

face robot中文教程

包含4節(jié)視頻教程
關注4.3萬

講解face robot運動捕捉表情動畫的綁定教程。face robot是xsi的獨立模塊,專門制作高精度電影級表情動畫。

關閉

Unity3D將來時:IL2CPP(下)


版本準備

前文詳細的介紹了IL2CPP的來龍去脈,這里用一個實際的例子來看看Unity3D里的IL2CPP都為我們做了哪些工作以及在使用的過程中會遇到哪些問題。

IL2CPP應用的第一個平臺是WebGL,為了讓游戲可以一鍵部署到基于WebGL的瀏覽器中,Unity3D Script工作組的大牛們找到了一個絕妙的解決方案:不僅解決了C#,Unity Script語言兼容問題,還解決了客戶端源碼泄漏問題。這個功能在Unity5.0 Beta版中提供了測試。

IL2CPP的第二個試用平臺是iOS 64位版。大家都知道蘋果已經發(fā)了最后通牒,全新App必須在15年2月1日支持64位CPU,而已經上架的游戲也必須在15年6月1日更新的時候支持64位。這個64位編譯就是交由IL2CPP完成的。具體到版本是 Unity 4.6.1 p5,Unity4.6.2和Unity 4.6.2 p1。本文后面都使用4.6.2 p1版本來進行演示。

創(chuàng)建項目,加入代碼
創(chuàng)建一個空的項目,加入兩個cs文件,一個叫IL2CPPCompatible.cs,另外一個是IL2CPPStudy.cs。前者主要用來測試代碼在IL2CPP中的兼容性,后者用來產生C++代碼,用來做對比分析。

以下是兩個文件的詳細內容:

IL2CPPCompatible.cs
這個文件中有兩個兼容性測試函數。一個函數使用ThreadPool.QueueUserWorkItem啟動一個新的線程。另一個則是SSL認證函數:ssl.AuthenticateAsClient (hosturl); 之所以寫這兩個函數是因為上述4.6.x IL2CPP對他們支持的還不是很好,會產生問題,這個我們在后面會詳細講到。

IL2CPPStudy.cs

using UnityEngine;
using System.Collections;
using System.IO;
using System.Threading;

public class CoconutClassStudy
{
        public int inta;
        public int intb;

        public int Add()
        {
                return inta + intb;
        }

        public CoconutClassStudy(int a, int b)
        {
                inta = a;
                intb = b;
        }

        public void IOTest(string filename)
        {
                if (File.Exists (filename)) {
                        FileStream fs = File.Open(filename, FileMode.Create);
                        fs.Close();

                }
        }

        public void ThreadTest()
        {
                Thread a =new Thread(delegate(object state) {
                        Debug.Log ("Thread Started");
                });
               
                a.Start ();
        }
}

public class IL2CPPStudy : MonoBehaviour {

        // Use this for initialization
        void Start () {
                Debug.Log (CoconutFuncStudy (10 , 20));
                CoconutClassStudy cc = new CoconutClassStudy (50, 60);
                Debug.Log (cc.Add ());
                cc.IOTest("test.txt");
                cc.ThreadTest ();
                Debug.Log (cc.GetType ());
        }
        
        // Update is called once per frame
        void Update () {
        
        }

        int CoconutFuncStudy(int a, int b)
        {
                return a + b;
        }
}

這個文件里面的內容就更簡單了:一個CoconutClassStudy類,里面有一個構造函數,一個Add函數和一個IOTest函數。另外在MonoBehaviour的Start()中,創(chuàng)建這個類的實例,并調用這兩個函數。這個源碼可以讓我們研究以下幾個方面:
1.cs的類在經過IL2CPP以后如何在CPP文件中表達
2.C#的IO操作經過IL2CPP以后如何在CPP文件中表達
3.當調用new關鍵字在堆里產生一個實例的時候CPP文件又是如何做的
4.開啟一個線程的操作IL2CPP會如何翻譯
5.調用cc.GetType()的行為IL2CPP如何處理

有了這連個文件后我們要做的第一件事情是生成XCode項目:
選擇IL2CPP編譯模塊,然后Build,生成XCode項目。
打開項目,在項目結構中打開Classes目錄,可以看到多了一個Native的子目錄
IL2CPP轉換出的所有文件都在其中。
我們寫的邏輯代碼,都在Assembly-CSharp.cpp中,除了這個文件,Native文件夾中還有很多以Bulk開頭的文件,這些其實是IL2CPP把一些必要C#庫翻譯到CPP形成的文件。
像Bulk_Generics_x.cpp和System.Collections.Generic有關。
Bulk_UnityEngine.UI_x.cpp則和Unity自帶的UI有關。

讓我們粗略的分析下在CPP文件中前面的5條都是如何實現的:
1.cs的類在經過IL2CPP以后如何在CPP文件中表達


我們的CoconutClassStudy類在CPP文件中變成了一個Struct,繼承于Object_t4。那這個Object_t4又是什么呢?

聰明的你一看注釋就知道了吧,沒錯,這個就是C#中的萬物之源,System.Object。

既然我們C#的類變成了Struct,那類里面的函數都去哪里了呢?帶著這個疑問,我們來看第二條。

2.C#的IO操作經過IL2CPP以后如何在CPP文件中表達
在CoconutClassStudy類中有一個成員函數:IOTest。在CPP中,我們看到了如下的實現:

類中的函數變成了一般的全局函數,函數名字是類名加上函數名,最后加上一個后綴而成。而原本C#中的File.Exists和File.Open函數都有了相應的C++實現。

3.當調用new關鍵字在堆里產生一個實例的時候CPP文件又是如何做的?
C#代碼中我們在Start函數中有一個顯示的New,找到相應C++代碼:

可以看到代碼調用了一個叫il2cpp_codegen_object_new的函數。而這個函數最終調用了IL2CPP VM中的New函數,分配了屬于GC管理的內存。

接下來第四條
4.開啟一個線程的操作IL2CPP會如何翻譯

C#中的System.Thread,在C++中是一個Thread_t26相當巨大的結構,在New出了這個結構之后,設置線程入口函數,最后調用Thread_Start_m47啟動線程。這個函數就是對應System.Threading.Thread.Start()


        我們看最后一條
5.調用cc.GetType()的行為IL2CPP如何處理。找到C++中的對應Start函數:

首先我們看到了對應C#中的Type的C++實現:Type_t28,其次是GetType()這個函數在C++中的實現,最后發(fā)現是調到了IL2CPP的VM函數:


在這些C++的實現中,細心的讀者可能會發(fā)現他們時時刻刻都在使用MethodInfo和TypeInfo這樣的信息。這個就是Unity Script項目組提到的Metadata。Metadata指的是非邏輯代碼,而是函數,結構,變量以及類本省的一些信息。比如名字,類型等。這個Metadata提供C++代碼和后臺的IL2CPP VM運行時必要的信息。

以上5條只是很簡單的例子,大家如果對IL2CPP的轉換感興趣,可以自己寫出想要了解的測試代碼,然后再對比CPP文件看其實現。

前方有坑,請小心
新的事物總是伴隨著問題,特別是在軟件行業(yè),Bug是不可避免的。就目前階段而言,IL2CPP還有不少問題。這個就是項目中IL2CPPCompatible.cs存在的意義:做兼容性測試。大家在實際的項目中如果遇到了問題,可以在這個文件中追加測試代碼。下面的表格把我們遇到的已知問題做一個列舉,供參考。


鏈接可執(zhí)行文件zlib報錯
ThreadPool.QueueUserWorkItem運行報錯
SSL.AuthenticateAsClient運行報錯

Unity 4.6.1 p5
發(fā)生
發(fā)生
發(fā)生

Unity 4.6.2 f1
發(fā)生
發(fā)生
發(fā)生

Unity 4.6.2 p1
修正
修正
發(fā)生







IL2CPP總結以及我們的建議
IL2CPP是Unity核心進行的很重要的進化之一。就現在來看,好處有以下幾點:

1.運行速度加快,游戲安裝尺寸減小,內存占用降低

2.除了可以Mono調試C#之外,我們又多了一種選擇:Native C++ 源碼級調試(不知道你們什么感覺,我對Unity C#調試頗有意見,經常連不上調試器,而且調試過程中常常宕機。換成用原生IDE調試C++代碼,就爽很多啦)。

3.可以快速的支持新的平臺,當然這點對我們關系不大。

帶來的問題:
1.由于原來由Mono VM的IL代碼全部變成了CPP,導致項目中多了很多CPP代碼,編譯時間會顯著增加。

2.IL2CPP還有各種Bug,可能會導致原來的代碼不能很好的編譯運行。需要等待Unity版本迭代。

3.鑒于C++靜態(tài)語言的特性,我們不能使用諸如System.Reflection.Emit這樣的動態(tài)代碼。(C# ATO方式編譯)

給使用Unity開發(fā)者的建議:
IL2CPP是大勢所趨,加上蘋果強制使用64位支持,意味著到了6月1號,所有用Unity開發(fā)的游戲都要用到新的編譯方式。如果你的項目比較大,應該立刻開始嘗試IL2CPP,以便發(fā)現問題,并開始解決。

clarisse搭建3D天空之城拉普達全過程 clarisse搭建3D天空之城拉普達全過程

朱峰社區(qū)網頁版
朱峰社區(qū)網頁版(手機掃描-分享-添加到屏幕)


朱峰社區(qū)公眾號
朱峰社區(qū)微信公眾號(微信掃一掃-關注)

資源說明圖文教程無法下載,只能觀看圖片和文字。
版權規(guī)則本站圖文皆來自互聯網共享資源,如涉及到版權請查看版權規(guī)則。本平臺提供圖文僅可用于個人學習,如用于商業(yè)請購買正版。您必須遵守的版權規(guī)則

未知用戶

未知用戶

2005-2025 朱峰社區(qū) 版權所有 遼ICP備2021001865號-1
2005-2025 ZhuFeng Community All Rights Reserved

VIP

朱峰社區(qū)微信公眾號

回頂部

1.復制文本發(fā)給您的QQ好友或群、微信等;好友點擊鏈接以后,轉發(fā)就成功了。 2.如朋友點擊您的鏈接,您需要需刷新一下才行;同一個好友僅能點擊一次。
購買VIP,觀看所有收費教程!