今天据说了一个颇有意思的需求,把Unity游戏打成一个包,嵌入到原生APP中git
正好两种技术栈我都有过相关经验,因此手痒实现一下!github
版本app
Unity 2019.2.0f1框架
Xcode9.3.1ide
建立一个Unity工程ui
拖入一个Cube和Text控件atom
而后BuildSetting中切换到iOSspa
注意若是须要用模拟器调试 须要在
Player Settings
中把Other Settings
中的Target SDK
切换为Simulator SDK
3d![]()
Unity2019.2.0f中勾选
Auto Graphics API
并不会添加依赖 须要手动取消Auto Graphics API
并在Graphics APIs
中添加OpenGLES3
调试![]()
而后点击Build
![]()
Unity默认在iOS AppDelegate
中的applicationDidBecomeActive
调用一个startUnity:
方法 若是要自定义唤起时间,则须要改变这个方法的调用时机
在UnityAppController
修改并添加如下代码
- (void)applicationDidBecomeActive:(UIApplication*)application
{
::printf("-> applicationDidBecomeActive()\n");
[self removeSnapshotView];
if (_unityAppReady)
{
if (UnityIsPaused() && _wasPausedExternal == false)
{
UnityWillResume();
UnityPause(0);
}
if (_wasPausedExternal)
{
if (UnityIsFullScreenPlaying())
TryResumeFullScreenVideo();
}
UnitySetPlayerFocus(1);
}
else if (!_startUnityScheduled)
{
_startUnityScheduled = true;
// 替换startUnity:为startSelfIOSView
[self performSelector: @selector(startSelfIOSView) withObject: application afterDelay: 0];
}
_didResignActive = false;
}
// 建立原生页面和控件,本身控制唤起Unity时机
- (void)startSelfIOSView
{
UIViewController *vc = [[UIViewController alloc] init];
vc.view.frame = [UIScreen mainScreen].bounds;
vc.view.backgroundColor = [UIColor whiteColor];
UIButton *btn = [[UIButton alloc]initWithFrame:CGRectMake(100, 100, 200, 50)];
btn.backgroundColor = [UIColor blueColor];
[btn setTitle:@"跳转到Unity界面" forState:UIControlStateNormal];
// 按钮被点击时唤起Unity项目
[btn addTarget:self action:@selector(startUnity:) forControlEvents:UIControlEventTouchUpInside];
[vc.view addSubview:btn];
[_window addSubview:vc.view];
}
复制代码
而后就能够经过咱们的定义的时机唤起Unity了
由于Unity界面跳转到IOS界面涉及到了暂停Unity因此咱们须要实现一个单例来判断Unity的暂停或启动
LARManager.h
#import <Foundation/Foundation.h>
@interface LARManager : NSObject
/** 是否暂停Unity */
@property (assign, nonatomic) BOOL unityIsPaused;
+ (instancetype)sharedInstance;
@end
复制代码
LARManager.m
#import "LARManager.h"
@implementation LARManager
+ (instancetype)sharedInstance
{
static LARManager *manager;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
manager = [[self alloc] init];
});
return manager;
}
- (instancetype)init
{
if (self = [super init]) {
self.unityIsPaused = NO;
NSLog(@"单例初始化成功");
}
return self;
}
@end
复制代码
而后在iOS中声明被Unity调用的方法
extern "C"
{
// 对Unity中的unityToIOS方法进行实现
void unityToIOS(char* str){
// Unity传递过来的参数
NSLog(@"%s",str);
UnityPause(true);
// 跳转到IOS界面,Unity界面暂停
[LARManager sharedInstance].unityIsPaused = YES;
// GetAppController()获取appController,至关于self
// UnityGetGLView()获取UnityView,至关于_window
// 点击按钮后跳转到IOS界面,设置界面为IOS界面
GetAppController().window.rootViewController = GetAppController().vc;
}
}
复制代码
在Unity中调用
[DllImport("__Internal")]
private static extern void unityToIOS (string str);
// 按钮点击后切换到iOS界面发送一个字符串
public void ButtonClick() {
unityToIOS("Hello iOS");
}
复制代码
实现效果:
在上个例子中已经展现了Unity向iOS传值的方法 在iOS中在extern "C"
中声明方法,而后在Unity中添加方法属性并添加标签[DllImport("__Internal")]
而后就能够直接调用了
在Unity项目中添加Test.h
Test.m
Test.h
extern "C"
{
extern void outputAppendString (char *str1, char *str2);
}
Test.m
#import <Foundation/Foundation.h>
void outputAppendString (char *str1, char *str2) {
NSString *string1 = [[NSString alloc] initWithUTF8String:str1];
NSString *string2 = [[NSString alloc] initWithUTF8String:str2];
NSLog(@"###%@", [NSString stringWithFormat:@"%@ %@", string1, string2]);
}
复制代码
而后两个文件Include Platforms
设置为iOS
而后添加一个按钮绑定事件
// 导入OC文件
[DllImport("__Internal")]
static extern void outputAppendString (string str1, string str2);
public void ButtonClickCalliOS() {
#if UNITY_IPHONE
outputAppendString("Hello", "World");
#endif
}
复制代码
就能够在不作任何iOS操做的状况下 把HelloWordl传入到iOS中啦~
实现效果:
iOS向Unity传值主要经过void UnitySendMessage(const char* obj, const char* method, const char* msg);
这个方法 这个方法能够传入三个参数:
总之就是删除Unity默认的启动时机
而后再经过自定义的时机跳转到Unity界面 或着跳回到原生界面
甚至能够用iOS的原生控件去操做Unity的对象
这样 iOS部分的开发 和 Unity部分的开发就能够同时进行了
项目地址: github.com/Lafree317/i…
参考文章: iOS与Unity3d交互-Larrycal: www.jianshu.com/p/4c49655af…
iOS 与 unity3D 交互整合的那些事: juejin.im/entry/58abd…
随缘更新RN/Week或其它移动端框架和Unity的交互