UnityAppController的定制以及Unity引擎的IL2CPP機

開發(fā) Unity3d 手機游戲的時候,不免要和第三方 SDK 打交道。于是總是需要實現(xiàn)自己的 AppController 來維護 SDK 的生命周期。

Unity3d 提供了一套插件機制,可以很方便地在項目中使用自己的 CustomAppController 繼承并重寫默認的 UnityAppController 的方法。

CustomAppController

在 Unity 插件目錄下創(chuàng)建以下文件:

?/path/to/unity/project/Assets/Plugins/iOS/CustomAppController.mm?

注意:

文件名必須是 ___AppController,前綴可自選,但不能省略;否則在 Build 項目的時候,會被移動到錯誤的目錄中去。

下面是集成BBase的入口,也是程序的入口

`//`

`//  CustomAppController.m`

`// `

`#import  "UnityAppController.h"`

`#import <BBase/BBaseManager.h>`

`@interface CustomAppController : UnityAppController`

`@end`

`IMPL_APP_CONTROLLER_SUBCLASS (CustomAppController)`

`@implementation CustomAppController`

`- (BOOL)application:(UIApplication*)application didFinishLaunchingWithOptions:(NSDictionary*)launchOptions`

`{`

`    [super application:application didFinishLaunchingWithOptions:launchOptions];`

`    [BBaseManager.sharedManager loadConfigureWithApplication:application registerPushNotificationLater:YES itunesConnectSharedSecret:@"" needReceiptVerification:YES gdprAppName:@"" gdprAgreementLink:@"" gdprPolicyLink:@"" ezalterDiversions:nil defaultEzalterParams:nil activateSuccessHandler:^(NSDictionary * _Nonnull json, NSString * _Nullable token) {`

`    } activateFailureHandler:^(NSError * _Nonnull error) {`

`    } activeSuccessHandler:^(NSDictionary * _Nonnull json) {`

`    } activeFailureHandler:^(NSError * _Nonnull error) {   `

`    }];`

 `return YES;`

`}`

`@end`

在 Build iOS Project 的時候,Unity 會自動把 CustomAppController.mm 復制到 ?/path/to/project/Libraries/CustomAppController.mm?

而原來的 UnityAppController.mm 則在 ?/path/to/project/Classes/UnityAppController.mm?

Unity 通過 ** IMPL_APP_CONTROLLER_SUBCLASS **知道要使用我們定制的 CustomAppController 而不是使用默認的 UnityAppController

IMPL_APP_CONTROLLER_SUBCLASS

UnityAppController.h 里面有這樣一個宏:

`#define IMPL_APP_CONTROLLER_SUBCLASS(ClassName) \`

`@interface ClassName(OverrideAppDelegate)       \`

`{                                               \`

`}                                               \`

`+(void)load;                                    \`

`@end                                            \`

`@implementation ClassName(OverrideAppDelegate)  \`

`+(void)load                                     \`

`{                                               \`

`    extern const char* AppControllerClassName;  \`

`AppControllerClassName = #ClassName;        \`

`}                                               \`

`@end`

將這個宏加到 CustomAppController.mm 中,即可實現(xiàn)自動設置 AppControllerClassName :

`IMPL_APP_CONTROLLER_SUBCLASS (CustomAppController)`

IMPL_APP_CONTROLLER_SUBCLASS 使用了兩個 Objective-C 的特性,一是 ?category? ,用來給已有的類擴展新的方法;二是 ?+(void)load? 靜態(tài)方法,它會在運行時 CustomAppController 類被加載到內(nèi)存中時觸發(fā),這個時間點比 ?int main()? 函數(shù)還要早,所以能夠提前“篡改” ?AppControllerClassName?,達到我們的目的。

  • 程序入口
    程序的入口為main.mm文件,通過IMPL_APP_CONTROLLER_SUBCLASS 調(diào)用了自定義繼承UnityAppController的 CustomAppController文件,在該文件的 下面這個方法- (BOOL)application:(UIApplication)application didFinishLaunchingWithOptions:(NSDictionary)launchOptions; 中注冊了BBase,調(diào)用父類UnityAppController中的方法,實現(xiàn)UI的創(chuàng)建

iOS平臺Unity引擎的IL2CPP機制

實現(xiàn)原理

Unity引擎作為目前最為主流的3D游戲開發(fā)引擎,游戲平臺移植性非常好,Unity引擎4.6.2之后的版本采用了IL2CPP機制支持IOS平臺64位游戲編譯,針對IL2CPP機制進行深入分析之后有利于評估IOS平臺的Unity游戲安全性。

image

Unity引擎采用IL2CPP機制在Mac平臺成功編譯之后,會生成一個完整的XCode工程,Unity游戲邏輯代碼采用C#編寫,游戲開發(fā)方的C#代碼最終會生成在/Classes/Native目錄中,對應文件結(jié)構(gòu)如下圖所示:

image

UI顯示機制

     Unity導出的iOS工程里面的結(jié)構(gòu)大致是這樣的,有一個Window,Window上有一個UnityView,但是并沒有控制器,也沒有根控制器,雖然在導出的iOS工程中Classes文件夾下的UnityAppController中有rootController的屬性,但是上面也標注為空~ 直接在window上顯示Unity界面的
image

導出xcode項目后,會產(chǎn)生DisplayManager 這樣的一個顯示管理器文件, 該文件中會輔助UnityView,Keyboard等等Unity轉(zhuǎn)成iOS的View的顯示,在DisplayManager 這個類中,引入了EAGLContext,通過OpenGL 去實現(xiàn)UI 的繪制

注釋:

1. CAEAGLLayer 支持在iOS和tvOS應用程序中繪制OpenGL內(nèi)容的圖層。

2.?EAGLContext?對象管理一個OpenGL ES 渲染上下文 狀態(tài)信息,命令和使用OpenGL ES繪制所需要的資源。要執(zhí)行OpenGL ES命令,您需要當前的渲染上下文。

補充:

Unity中的ViewController

Unity中沒有viewcontroller的概念,頁面之間的切換其實就是在同一個viewcontroller上重繪不同的view,一個叫做UnityView的UIView來顯示繪制的頁面。

但既然要在iOS上顯示界面,就必須要有一個viewcontroller的載體。Unity中沒有,所以Unity中有一個_viewControllerForOrientation[5]的數(shù)組來維持屏幕4個方向的viewcontroller+autorotate的viewcontroller,也就是說Unity中從始至終最多只有5個viewcontroller。

viewcontroller如何切換

如果現(xiàn)在要顯示豎屏頁面,就從數(shù)組中取出豎屏的viewcontroller,如果沒有就創(chuàng)建一個,然后將_unityView賦值給豎屏的viewcontroller.view,如果現(xiàn)在要進入橫屏頁面,就從數(shù)據(jù)中取出橫屏的viewcontroller,然后將_unityView賦值給橫屏的viewcontroller.view。

createDisplayLink

那么手機從豎屏變成橫屏后什么時候重繪呢,什么時候顯示呢?這個時候就需要createDisplayLink函數(shù),它會創(chuàng)建一個60Hz的timer,為什么是60,因為iPhone的屏幕刷新率就是60Hz,每次的timer執(zhí)行函數(shù)中會去檢查當前要顯示哪個viewcontroller,以及是否需要重繪,然后顯示

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容