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