今天據說了一個頗有意思的需求,把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的交互