iOS与Unity3d数据交互

2019-05-15  本文已影响0人  西充小凡哥

前言

  1. IOS与团结之间的界面切换
  2. IOS与团结之间的函数调用以及传值

IOS与团结之间的界面切换

在IOS和Unity3D跨平台开发中,基本就是两个平台之间的数据交互和界面切换,而界面交互是重中之重。利用Unity3D可以实现一些IOS原生界面所不具有的效果,而IOS原生界面则在整个程序界面中又显得更和谐一些。所以无论是功能还是美观,两者之间的界面交互都很常用。

前期统一准备

我们要用统一和IOS的界面切换和数据交互,就必然要先实现一个统一程序。我就默认读者都会一些统一基础和OC技术吧。

image
using UnityEngine;
using System.Collections;
using System.Runtime.InteropServices;
public class Test : MonoBehaviour {
    public GameObject cube;

    // DllImport这个方法相当于是告诉Unity,有一个unityToIOS函数在外部会实现。
    // 使用这个方法必须要导入System.Runtime.InteropServices;
    [DllImport("__Internal")]
    private static extern void unityToIOS (string str);

    void OnGUI()
    {
        // 当点击按钮后,调用外部方法
        if (GUI.Button (new Rect (100, 100, 100, 30), "跳转到IOS界面")) {
            // Unity调用ios函数,同时传递数据
            unityToIOS ("Hello IOS");
        }
    }
    // 向右转函数接口
    void turnRight(string num){
        float f;
        if (float.TryParse (num, out f)) {// 将string转换为float,IOS传递数据只能用以string类型
            Vector3 r = new Vector3 (cube.transform.rotation.x, cube.transform.rotation.y - 10f, cube.transform.rotation.z);
            cube.transform.Rotate (r);
        }
    }
    // 向左转函数接口
    void turnLeft(string num){
        float f;
        if (float.TryParse (num, out f)) {// 将string转换为float,IOS传递数据只能用以string类型
            Vector3 r = new Vector3 (cube.transform.rotation.x, cube.transform.rotation.y - 10f, cube.transform.rotation.z);
            cube.transform.Rotate (r);
        }
    }
}

image

从IOS界面切换到统一界面

const char* AppControllerClassName = "UnityAppController";
int main(int argc, char* argv[])
{
    @autoreleasepool
    {
        UnityInitTrampoline();
        UnityParseCommandLine(argc, argv);
        RegisterMonoModules();
        NSLog(@"-> registered mono modules %p\n", &constsection);
        RegisterFeatures();

        // iOS terminates open sockets when an application enters background mode.
        // The next write to any of such socket causes SIGPIPE signal being raised,
        // even if the request has been done from scripting side. This disables the
        // signal and allows Mono to throw a proper C# exception.
        std::signal(SIGPIPE, SIG_IGN);

        UIApplicationMain(argc, argv, nil, [NSString stringWithUTF8String:AppControllerClassName]);
    }

    return 0;
}

image
  - (void)applicationDidBecomeActive:(UIApplication*)application
{
    ::printf("-> applicationDidBecomeActive()\n");
    [self removeSnapshotView];
    if(_unityAppReady)
    {
        if(UnityIsPaused() && _wasPausedExternal == false)
        {
            UnityWillResume();
            UnityPause(0);
        }
        UnitySetPlayerFocus(1);
}
    else if(!_startUnityScheduled)
    {
        _startUnityScheduled = true;
        [self performSelector:@selector(startSelfIOSView) withObject:application afterDelay:0];
    }
    _didResignActive = false;
}
- (void)startSelfIOSView
{
    UIViewController *vc = [[UIViewController alloc] init];
    vc.view.backgroundColor = [UIColor blueColor];
    vc.view.frame = [UIScreen mainScreen].bounds;
    UIButton *btn = [[UIButton alloc]initWithFrame:CGRectMake(100, 100, 70, 30)];
    btn.backgroundColor = [UIColor whiteColor];
    [btn setTitle:@"跳转到Unity界面" forState:UIControlStateNormal];
    [btn addTarget:self action:@selector(startUnity:) forControlEvents:UIControlEventTouchUpInside];
    [vc.view addSubview:btn];
    [_window addSubview:vc.view];
}

image

从统一界面跳转到IOS界面

在统一脚本中,我们已经添加了一个按钮,并且给了接口。所以我们可以利用这个按钮实现跳转到IOS界面。

在IOS工程中调用统一函数的方式是利用Ç语言接口。在IOS工程中利用形如

extern "C"
{
    void functionName(parameter){
    // do something
    }
}

这样的形式来调用统一中的函数。

因为统一界面跳转到IOS界面涉及到了暂停团结所以我们需要实现一个单例来判断统一的暂停或启动

//  LARManager.m
//  Unity-iPhone
//
//  Created by 柳钰柯 on 2016/12/15.
//
//
#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

实现单例之后的startSelfIOSView和unityToIOS函数
- (void)startSelfIOSView
{
    // 单例变量unity没有暂停,设置为no
    [LARManager sharedInstance].unityIsPaused = NO;
    // IOS原生界面
    UIViewController *vc = [[UIViewController alloc] init];
    vc.view.backgroundColor = [UIColor blueColor];
    vc.view.frame = [UIScreen mainScreen].bounds;
    // 添加按钮
    UIButton *btn = [[UIButton alloc]initWithFrame:CGRectMake(100, 100, 200, 30)];
    btn.backgroundColor = [UIColor whiteColor];
    btn.titleLabel.backgroundColor = [UIColor blackColor];
    [btn setTitle:@"跳转到Unity界面" forState:UIControlStateNormal];
    [btn addTarget:self action:@selector(startUnity:) forControlEvents:UIControlEventTouchUpInside];
    // 在界面上添加按钮
    [vc.view addSubview:btn];
    self.vc = vc;
    NSLog(@"设置界面为IOS界面");
    self.window.rootViewController = vc;
}
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;
    }
}

image

IOS与团结之间的函数调用以及传值

在上一步中,其实我们已经实现了IOS和统一函数调用和一部分传值。现在更详细的说明一下。

统一调用IOS函数并进行传值

    [DllImport("__Internal")]
    private static extern void functionName (ParameterType Parameter);

为固定格式。这一句表明会在外部引用一个叫functionName(ParameterType参数)的函数,参数为参数。在IOS程序中实现上一步中已经讲过,不再赘述。

IOS调用团结函数并进行传值

IOS调用团结函数需要用到UnitySendMessage方法,方法中有三个参数

UnitySendMessage(“gameobject”,“Method”,msg);
向统一发送消息
参数一为统一脚本挂载的gameobject
参数二为unity脚本中要调用的方法名
参数三为传递的数据,* 注意:传递的数据只能是字符类型**

我们利用在统一工程中已经写好的接口来试试数据的传递。

- (BOOL)application:(UIApplication*)application didFinishLaunchingWithOptions:(NSDictionary*)launchOptions
{
    /*省略了一些Unity的操作*/
  /*.....*/
    [self createUI];
    [self preStartUnity];
  // 添加右旋按钮
  UIButton *rightBtn = [[UIButton alloc] initWithFrame:CGRectMake(10, 150, 100, 30)];
  rightBtn.backgroundColor = [UIColor whiteColor];
  [rightBtn setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
  [rightBtn setTitle:@"向右旋转" forState:UIControlStateNormal];
  [rightBtn addTarget:self action:@selector(turnRight) forControlEvents:UIControlEventTouchUpInside];
  self.rightBtn = rightBtn;
  // 添加左旋按钮
  UIButton *leftBtn = [[UIButton alloc] initWithFrame:CGRectMake(10, 200, 100, 30)];
  leftBtn.backgroundColor = [UIColor whiteColor];
  [leftBtn setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
  [leftBtn setTitle:@"向左旋转" forState:UIControlStateNormal];
  [leftBtn addTarget:self action:@selector(turnLeft) forControlEvents:UIControlEventTouchUpInside];
  self.leftBtn = leftBtn;
  // 在Unity界面添加按钮
  [UnityGetGLViewController().view addSubview:_rightBtn];
  [UnityGetGLViewController().view addSubview:_leftBtn];
    // if you wont use keyboard you may comment it out at save some memory
    [KeyboardDelegate Initialize];
    return YES;
}
// 左旋按钮响应事件
- (void)turnRight
{
    const char* str = [[NSString stringWithFormat:@"10"] UTF8String];
    UnitySendMessage("Main Camera", "turnRight", str);
}
// 右旋按钮响应事件
- (void)turnLeft
{
    const char* str = [[NSString stringWithFormat:@"10"] UTF8String];
    UnitySendMessage("Main Camera", "turnLeft", str);
}

image

总结

  // 声明外部函数
    [DllImport("__Internal")]
    private static extern void functionName (ParameterType Parameter);

extern "C"
{
    void functionName(parameter){
    // do something
    }
}

结语

作者:Larrycal
链接:https://www.jianshu.com/p/4c49655aff8b
来源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。

上一篇下一篇

猜你喜欢

热点阅读