程序员

UnityAppController的定制以及Unity引擎的I

2020-03-09  本文已影响0人  lumic000

开发 Unity3d 手机游戏的时候,不免要和第三方 SDK 打交道。于是总是需要实现自己的 AppController 来维护 SDK 的生命周期。

Unity3d 提供了一套插件机制,可以很方便地在项目中使用自己的 CustomAppController 继承并重写默认的 UnityAppController 的方法。

CustomAppController

在 Unity 插件目录下创建以下文件:

​/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 中,即可实现自动设置 AppControllerClassName :

`IMPL_APP_CONTROLLER_SUBCLASS (CustomAppController)`

IMPL_APP_CONTROLLER_SUBCLASS 使用了两个 Objective-C 的特性,一是 ​category​ ,用来给已有的类扩展新的方法;二是 ​+(void)load​ 静态方法,它会在运行时 CustomAppController 类被加载到内存中时触发,这个时间点比 ​int main()​ 函数还要早,所以能够提前“篡改” ​AppControllerClassName​,达到我们的目的。

iOS平台Unity引擎的IL2CPP机制

实现原理

Unity引擎作为目前最为主流的3D游戏开发引擎,游戏平台移植性非常好,Unity引擎4.6.2之后的版本采用了IL2CPP机制支持IOS平台64位游戏编译,针对IL2CPP机制进行深入分析之后有利于评估IOS平台的Unity游戏安全性。

image

Unity引擎采用IL2CPP机制在Mac平台成功编译之后,会生成一个完整的XCode工程,Unity游戏逻辑代码采用C#编写,游戏开发方的C#代码最终会生成在/Classes/Native目录中,对应文件结构如下图所示:

image

UI显示机制

     Unity导出的iOS工程里面的结构大致是这样的,有一个Window,Window上有一个UnityView,但是并没有控制器,也没有根控制器,虽然在导出的iOS工程中Classes文件夹下的UnityAppController中有rootController的属性,但是上面也标注为空~ 直接在window上显示Unity界面的
image

导出xcode项目后,会产生DisplayManager 这样的一个显示管理器文件, 该文件中会辅助UnityView,Keyboard等等Unity转成iOS的View的显示,在DisplayManager 这个类中,引入了EAGLContext,通过OpenGL 去实现UI 的绘制

注释:

1. CAEAGLLayer 支持在iOS和tvOS应用程序中绘制OpenGL内容的图层。

2.​EAGLContext​对象管理一个OpenGL ES 渲染上下文 状态信息,命令和使用OpenGL ES绘制所需要的资源。要执行OpenGL ES命令,您需要当前的渲染上下文。

补充:

Unity中的ViewController

Unity中没有viewcontroller的概念,页面之间的切换其实就是在同一个viewcontroller上重绘不同的view,一个叫做UnityView的UIView来显示绘制的页面。

但既然要在iOS上显示界面,就必须要有一个viewcontroller的载体。Unity中没有,所以Unity中有一个_viewControllerForOrientation[5]的数组来维持屏幕4个方向的viewcontroller+autorotate的viewcontroller,也就是说Unity中从始至终最多只有5个viewcontroller。

viewcontroller如何切换

如果现在要显示竖屏页面,就从数组中取出竖屏的viewcontroller,如果没有就创建一个,然后将_unityView赋值给竖屏的viewcontroller.view,如果现在要进入横屏页面,就从数据中取出横屏的viewcontroller,然后将_unityView赋值给横屏的viewcontroller.view。

createDisplayLink

那么手机从竖屏变成横屏后什么时候重绘呢,什么时候显示呢?这个时候就需要createDisplayLink函数,它会创建一个60Hz的timer,为什么是60,因为iPhone的屏幕刷新率就是60Hz,每次的timer执行函数中会去检查当前要显示哪个viewcontroller,以及是否需要重绘,然后显示

上一篇下一篇

猜你喜欢

热点阅读