iOS 與 Unity 的交互

前言

今天據說了一個頗有意思的需求,把Unity遊戲打成一個包,嵌入到原生APP中git

正好兩種技術棧我都有過相關經驗,因此手癢實現一下!github

版本app

Unity 2019.2.0f1框架

Xcode9.3.1ide

Show Me The Code

建立一個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

iOS喚起Unity

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界面跳轉到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傳值

第一種方法

在上個例子中已經展現了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傳值

iOS向Unity傳值主要經過void UnitySendMessage(const char* obj, const char* method, const char* msg);這個方法 這個方法能夠傳入三個參數:

  • 參數一爲unity腳本掛載的gameobject
  • 參數二爲unity腳本中要調用的方法名
  • 參數三爲傳遞的數據,*注意:傳遞的數據只能是char 類型

總結

總之就是刪除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的交互

相關文章
相關標籤/搜索