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的交互

相关文章
相关标签/搜索