本文屬于「Unity與iOS、Android平臺(tái)的整合」系列文章之一柑营,轉(zhuǎn)載請(qǐng)注明出處屈雄。
本文主要講解Unity導(dǎo)出的Xcode工程的目錄結(jié)構(gòu)。
我所用軟件的版本:
Unity 5.3.5f1
Xcode 7.3
前導(dǎo)步驟
第一步官套,創(chuàng)建一個(gè)新的工程 Build_to_iOS_Android
第二步酒奶,創(chuàng)建一個(gè)新文件 CSharpToCPP.cs
using UnityEngine;
public class CSharpToCPP
{
public void Func(int num)
{
if (num < 1)
{
return;
}
else
{
Debug.Log("Log:Time" + num);
}
}
}
第三步,創(chuàng)建
Plugins/iOS/iOS_EmptyMM.mm
StreamingAssets/ALL_EmptyTxt.txt
第四步奶赔,保存一下場(chǎng)景惋嚎,如下圖
第五步,選擇iOS平臺(tái)纺阔,Build導(dǎo)出Xcode工程
第六步瘸彤,打開所導(dǎo)出的Xcode工程
進(jìn)入正題
1鸵膏、程序入口
任何程序都有一個(gè)入口隙疚,Unity導(dǎo)出的Xcode工程中也不例外,通過下圖我們可以看到,在應(yīng)用的入口中創(chuàng)建了UnityAppController的對(duì)象浦译。
通過下圖我們可以看到穴肘,UnityAppController是繼承了UIApplicationDelegate命贴,至于它是什么我就不贅述了梢莽,大家可以看一下這一篇文章:簡(jiǎn)析UIApplication及UIApplicationDelegate
下圖為一個(gè)UIApplication的生命周期,我們可以看到系統(tǒng)事件存在著非常有用的監(jiān)聽臼朗,在UnityAppController.mm里面我們也可以看到對(duì)應(yīng)的函數(shù)邻寿,這意味著在Unity中一樣可以收到這些事件,以后我們將繼承UnityAppController视哑,并重寫這些監(jiān)聽绣否。
2、C# -> C++:
在Unity中挡毅,我們用的是C#蒜撮、JS進(jìn)行編程(我是C#黨),但是導(dǎo)出Xcode工程后跪呈,這些代碼都轉(zhuǎn)換成了C++代碼段磨。
在Player Settings里面我們可以看到腳本的運(yùn)行模式有兩種,一種是IL2CPP耗绿,另一種是Mono2x(以后肯定會(huì)被CPP替代苹支,我就不講了),通常我們會(huì)選擇IL2CPP误阻,因?yàn)樾矢摺?/p>
選擇IL2CPP我們的邏輯代碼將全部轉(zhuǎn)換為C++代碼债蜜,下圖為CSharpToCPP.cs轉(zhuǎn)換成的C++代碼。
以下代碼是上圖中的翻譯代碼究反,對(duì)比我們一開始寫的CSharpToCPP.cs里邏輯策幼,應(yīng)該能夠看懂其中的邏輯。
// System.Void CSharpToCPP::Func(System.Int32)
extern Il2CppClass* Int32_t2847414787_il2cpp_TypeInfo_var;
extern Il2CppClass* String_t_il2cpp_TypeInfo_var;
extern Il2CppClass* Debug_t1588791936_il2cpp_TypeInfo_var;
extern Il2CppCodeGenString* _stringLiteral2043233667;
extern const uint32_t CSharpToCPP_Func_m1441544591_MetadataUsageId;
extern "C" void CSharpToCPP_Func_m1441544591 (CSharpToCPP_t373417985 * __this, int32_t ___num0, const MethodInfo* method)
{
static bool s_Il2CppMethodIntialized;
if (!s_Il2CppMethodIntialized)
{
il2cpp_codegen_initialize_method (CSharpToCPP_Func_m1441544591_MetadataUsageId);
s_Il2CppMethodIntialized = true;
}
{
int32_t L_0 = ___num0;
if ((((int32_t)L_0) >= ((int32_t)1)))
{
goto IL_0008;
}
}
{
return;
}
IL_0008:
{
int32_t L_1 = ___num0;
int32_t L_2 = L_1;
Il2CppObject * L_3 = Box(Int32_t2847414787_il2cpp_TypeInfo_var, &L_2);
IL2CPP_RUNTIME_CLASS_INIT(String_t_il2cpp_TypeInfo_var);
String_t* L_4 = String_Concat_m389863537(NULL /*static, unused*/, _stringLiteral2043233667, L_3, /*hidden argument*/NULL);
IL2CPP_RUNTIME_CLASS_INIT(Debug_t1588791936_il2cpp_TypeInfo_var);
Debug_Log_m1731103628(NULL /*static, unused*/, L_4, /*hidden argument*/NULL);
return;
}
}
由于C++代碼是機(jī)器自動(dòng)生成的奴紧,可讀性催人尿下,所以最好參照自己的C#代碼進(jìn)行閱讀晶丘。
由于Unity -> Xcode -> 設(shè)備黍氮,編譯時(shí)間太過漫長(zhǎng)了,所以在問題排查時(shí)浅浮,我會(huì)嘗試注釋或簡(jiǎn)單修改C++代碼沫浆,實(shí)現(xiàn)問題定位等。
3滚秩、資源 StreamingAssets -> Data/Raw
Unity導(dǎo)出Xcode工程后专执,原工程中的各種資源都被壓縮、打包郁油、加密后存放在Data文件夾中本股,這一點(diǎn)和Android是一致的攀痊,網(wǎng)上也有很多資源解密的方法,大家有需要可以自行搜索拄显。
我們重點(diǎn)說一下Unity中的StreamingAssets文件夾苟径,關(guān)于這個(gè)文件的作用,大家可以看一下這篇文章:Unity3D研究院之手游開發(fā)中所有特殊的文件夾
通過下圖我們可以看到躬审,StreamingAssets文件夾中的ALL_EmptyTxt.txt文件被完整地拷貝到Data/Raw文件夾中棘街,實(shí)際上不光是文件,文件夾也會(huì)原封不動(dòng)地拷入該文件夾承边。
至于這有什么用遭殉,比如說,配置文件放在這里博助,上手機(jī)調(diào)試的話可以在Xcode工程中直接修改配置险污,而不需要到Unity里重新導(dǎo)出Xcode工程。
4翔始、Plugins/iOS -> Library/Plugins/iOS
Plugins/iOS文件夾中通常會(huì)放一些 *a.罗心、*h、*.m文件城瞎,這些文件將拷貝至在Xcode工程的Library/Plugins/iOS文件夾中渤闷,在Xcode編譯時(shí)也將被編譯。
實(shí)際操作過程中脖镀,我會(huì)把自己為iOS寫的OC飒箭、C、C++代碼蜒灰、SDK提供的.a文件放到里面弦蹂,以避免每次編譯后都要在Xcode工程里重新導(dǎo)入。
5强窖、Icon
在Unity的Player Settings是中凸椿,我們可以添加相應(yīng)的Icon
這些Icon圖片將被重新壓縮、命名最后放入下圖中的位置翅溺。
由于Unity內(nèi)只能導(dǎo)出這些分辨率大心月(比如iPadPro的icon無法導(dǎo)出),而且Unity會(huì)根據(jù)我們選擇的圖片壓縮格式重新生成Icon(如果格式?jīng)]選對(duì)容易圖片變模糊)咙崎,所以我選擇到Xcode工程中替換這些文件优幸。
6、閃屏
Unity在iOS有很多種閃屏方案褪猛,具體方案效果大家可以自行搜索~
下圖為常見的單圖片閃屏導(dǎo)出位置网杆,與Icon一樣,我一般在這邊替換,哦對(duì)碳却,不要忘了取消ShowUnitySplashScreen的勾選队秩。
7、Framework
在Unity的Plugins/iOS/中文件可以為自身簡(jiǎn)單勾選配置一些Framework依賴追城,見下圖刹碾。
這些依賴將自動(dòng)添加到Xcode工程中,我們可以在Frameworks文件夾檢查是否添加座柱。
8迷帜、Player Settings -> 設(shè)置
在Unity的Player Settings中存在著大量的配置,這些配置將反應(yīng)到Xcode工程中色洞,在下圖中圈出了部分戏锹,這些東西并不復(fù)雜,我也就不贅述了火诸。