做軟件開發幾年了,隨著經驗的增長,你會發現,很多時候遇到一些抓狂的問題,他并不是來源于技術本身的,而是來源于技術以外的一些周邊。
比如說運維、安全、流程、自動化、編譯構建啊等等。
我上一篇文章《Unity自動構建思考(1)|自動構建機器的選擇經驗和思考》中,提及了自動構建這件事情。在幾年的Unity游戲開發工作中,其中一個讓我非常抓狂的地方,就是使用Unity引擎進行iOS編譯出包。
為什么說使用Unity編譯iOS會很麻煩?
我們都知道,Unity游戲引擎,使用了Mono引擎作為它的腳本語言引擎,而蘋果iOS開發的官方語言是Objective-C和Swift(或其它方式編譯出來的靜態庫.a),編譯工作,必須是在Xcode工程上進行的。
所以,要進行Unity的蘋果編譯,本質上,首先要把Unity的工程,包括腳本、資源等等,轉換成Xcode工程。
(Unity編譯iOS,實質是轉換成Xcode工程)
這,就是麻煩的開始。
因為生成出的是Xcode工程,編譯的Xcode工程,也就是說,你在Unity上的一些開發知識,就變得不再有用了,你進入了iOS開發領域。
來到iOS開發領域,就要接受iOS工程編譯的洗禮,常見的坑有依賴庫、簽名、第三方插件集成幾個問題。
依賴庫,需要外掛腳本處理
在Unity5以前,比如Unity4,Unity有一個很蛋痛的設計,就是,它生成的那個Xcode工程,是不會幫你處理依賴的Framework的。
怎么理解這件事呢?
你比如說,游戲里面引用了一個第三方的庫插件(比如極光推送),這個插件需要引用了一個iOS靜態庫(jpush.a文件),但是問題是,這個.a庫可能依賴了一個UserNotifications.framework,Unity是并不知道你的.a靜態庫會對Framework有依賴的。
所以,生成出來的這一個Xcode工程,根本編譯不過,在編譯的階段,它就會告訴你,缺少了對某個Framework的依賴。
那這事怎么辦呢?一般來說,常見的解決方法是使用一些開源的Xcode工程修改工具,在Xcode編譯工程出來以后,對這個Xcode工程進行依賴庫的修改和補充。
比如我喜歡用Python寫成的mod-pbxproj;有的人喜歡Ruby寫成的XcodeProj,功能更強大。
一般自動化的Unity編譯,使用BuidPipeline.BuildPlayer命令后,這些工具就會出場,對Xcode進行工程層面的一些修改。
常見的操作就是諸如對一些依賴庫(Framework、Library)和iOS功能(比如GameCenter/In-App-Purchase等)進行添加、修改,盡可能做到Unity生成的工程,在經過腳本修改后,直接就編譯成功,減少人工干預。
簽名,各種小問題
蘋果對安全的投入是非常大的,從它的簽名機制就能看出來了——太tm麻煩了。
(Xcode 8中“自動管理簽名"功能)
其中有一次,Xcode 7升級到Xcode 8,增加了“自動管理簽名”的功能。在官方看來,他在這一個簽名流程進行了一些改進,還有優化簡化了這件事情。
但是對于當時我來說,還有公司的其他小伙伴來說,簡直崩潰。因為之前的手動簽名流程,都不再有效了。
這個“自動管理簽名”的功能,要求使用者,在iOS Developer登錄后,就能方便地進行Xcode的打包簽名管理。
問題是,實際的公司作業流程中,iOS證書一般是由發行方(運營商)進行頒發,并把證書文件發往研發方(游戲研發)。出于發行方的保密,研發方在打包iOS最終包時,使用的是具體的證書參數設置,而沒有具體的iOS Developer登錄權限。
對于這種流程,“自動管理簽名”這個功能,其實是沒啥作用的。你需要把它關閉掉,并且手動設置。起初為了達到這功能,我把開源項目mod-pbxproj也進行了一點小改,以達到“關閉自動管理簽名”這個功能。
(iOS簽名這件事,有挺不簡單的一整套安全體系,剛開始挺折騰的,你可以上網去搜索更多關于iOS簽名的內部實現機制)
第三方SDK的坑
Unity游戲開發,往往是多個渠道方同時發布的。比如說,我們的游戲在5個國家有語言版本,在5個國家有獨立合作的發行商,對應著5個發行商SDK...
游戲開發時,發行商SDK接入是一件非常的麻煩吃力不討好的事情,十分的折騰。所以這時候就有很多的“中介式SDK”的出現,比如我用過的有棱鏡、西瓜sdk,簡單來說,就是只要接入一次SDK,剩下的無數其它SDK接入的問題,都可以交由它們進行自動處理,節省成本。
盡管如此,但是有時候,也避免不了,需要對Xcode工程的Objective-C代碼進行修改或依賴庫處理。
比方說,上一個游戲,就需要加一個Facebook分享的功能。這個功能,“中介SDK”并沒有提供,那就只能自己對Xcode工程的部分Objective-C代碼進行定制了。
我們知道,Unity編譯iOS的本質,是生成一個Xcode工程。那就是說,每一次的Unity編譯,都會生成一個Xcode工程。
同樣就是說,你對一個Xcode工程進行部分代碼定制后,再進行一次Unity編譯,這些部分定制代碼就會消失。
像前面所說,在Unity編譯后,mod-pbxproj這些Xcode工程修改工具,就會出場,對Xcode工程進行自動化的匹配修改。但是一些第三方SDK的接入,可就不是修改依賴庫那么簡單了,它們經常需要對Objective-C語言的文件進行修改,添加一些Objective-C代碼。
這時候我一般的做法是,使用Python腳本,進行代碼的“搜索-替換”......
后記
其實在Unity 5新版中,對iOS依賴庫的處理能在Unity編輯器進行,Unity引擎在iOS編譯這方面其實還是一直有進步的。
之所以覺得Unity的iOS編譯麻煩,可能是因為我自己比較強調自動構建的全自動化,我發現有不少的其他項目組,一般是打出Xcode工程后,安排人手進行一些手動的操作,比如插代碼、處理依賴庫、接入第三方SDK、導出IPA等,都是通過在mac系統里的鼠標人為操作實現的。
雖然我所在的項目實現了全自動產出IPA,但是經常有一些外部因素會影響到最終的IPA文件生成,比如說....iOS簽名過期、系統版本更新、第三方SDK版本更新,都會影響到最終IPA的全自動產出。
這些外部因素影響到自動構建的特殊情況,有時確實無可奈何。要不就追加自動化的處理代碼,要不就放棄這部分自動,進行人工操作唄。
一個即將離開Unity界的程序員。算是寫給交接工作的同學,同學你看到了嗎。