Skip to content

原生层与unity通讯

通常从原生层想unity发送消息会使用UnityPlayer.UnitySendMessage("TargetName","MethodName","这是参数");
这要求我们的unity场景中存在一个名为TargetName的物体,且其上挂着一个包含MethodName方法的脚本,才能接收到相关数据,操作起来有些麻烦,今天介绍下另外一种方式。

android

在java中添加一个接口文件BLListener.java并在unity中继承此文件

java
package com.tuyazuo.unityhelper;

public interface BLListener {
    public void onMsg(String json); //数据处理方法,注意处理在非UI线程更新UI的问题
}

在unity中添加脚本BLListener.cs,用于接收android回调过来的消息

c#
using System.Collections;
using System.Collections.Generic;
#if UNITY_IPHONE
using System;
using System.Runtime.InteropServices;
#endif
using UnityEngine;

#if UNITY_ANDROID
/*=======================================
 * 数据接收对象,需继承 AndroidJavaProxy
 * 需实现 onMsg 方法,此方法供安卓调用传输数据
 *=======================================
 */
public class BLListener : AndroidJavaProxy
{
    public BLListener() : base("com.tuyazuo.unityhelper.BLListener") { }

    public void onMsg(string json)
    {
        // BLHelper.instance.onMsg(json);
    }
}
#endif

#if UNITY_IPHONE
public class BLListener
{
    [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
    public delegate void BLHandler(string msg);

    [AOT.MonoPInvokeCallback(typeof(BLHandler))]
    public static void onMsg(string json)
    {
        // BLHelper.instance.onMsg(json);
    }

    public IntPtr handler {
        get{
            BLHandler handler = new BLHandler(BLListener.onMsg);
            IntPtr ptr = Marshal.GetFunctionPointerForDelegate(handler);
            return ptr;
        }
    }
}
#endif

在自己的桥接类中调用安卓方法进行初始化,参考如下

c#
#if UNITY_ANDROID
    private static AndroidJavaClass _helper;
    public static AndroidJavaClass helper
    {
        get
        {
            if (_helper != null) return _helper;
            _helper = new AndroidJavaClass("com.tuyazuo.unityhelper.BLHelper");
            return _helper;
        }
    }
#endif

    //初始化方法
    public void Init(string param, BLListener listener)
    {
#if UNITY_ANDROID
        helper.CallStatic("init", param, listener);
#elif UNITY_IPHONE
        init(param, listener.handler);
#endif
    }

#if UNITY_IPHONE
    [DllImport("__Internal")]
    static extern void init(string param, System.IntPtr handler);
#endif

BLHelper.java文件参考如下

java
package com.tuyazuo.unityhelper;

import android.annotation.SuppressLint;
import android.app.Activity;

public class BLHelper {
    private BLListener listener; //接收数据对象

    //unity初始化专用
    public static void init(String param, BLListener listener) {
        this.listener = listener;
    }
}

当我们在安卓层需要发送数据时就可以直接调用listener.onMsg("xxx"),你可以在接口中自己定义更多方法。

ios

c#部分的代码已经在上面贴出。 在ios项目中新建文件BLHelper.mm

objective-c
#import <Foundation/Foundation.h>

//unity
typedef void (*BLHandler) (const char *object);


@interface BLHelper : NSObject <BLListener>

@property BLHandler handler;

@end


static BLHelper *_helper;

@implementation BLHelper

+ (BLHelper *)sharedInstance{
    if(_helper == nil)
        _helper = [[BLHelper alloc] init];
    return _helper;
}

- (void)onMsg:(NSDictionary *)msg{
    NSString *json = [[BLDelegate sharedInstance] obj2Json:msg];
    self.handler(getChar(json));
}

NSString *getString(char *str){
    return [NSString stringWithUTF8String:str];
}

const char *getChar(NSString *str){
    return [str cStringUsingEncoding:NSUTF8StringEncoding];
}

@end

extern "C" {

    void init(char *param, BLHandler handler){
        [[BLHelper sharedInstance] setHandler:handler];
        [[BLDelegate sharedInstance] init:getString(param) listener:[BLHelper sharedInstance]];
    }
}

在你的逻辑脚本(例如BLDelegate.h)中定义协议并在init方法中保存listener对象

objective-c
#import <Foundation/Foundation.h>

@protocol BLListener <NSObject>

@required

- (void)onMsg:(NSDictionary *)msg;

@end

@interface BLDelegate : NSObject

@property (nonatomic, strong) id<BLListener> listener;

+ (BLDelegate *)sharedInstance;
- (void)init:(NSString *)param listener:(id<BLListener>) listener;

@end

调用[self.listener onMsg:dic];就可以跟unity通讯了。