Unity和iOS 原生专题二 Unity和iOS原生交互相互传值的两个方案

一 、方案一 通过指针传值和使用 MonoPInvokeCallback 从C#层向C层注册回调函数

1.1 iOS调用Unity函数Unity 给iOS传值

第一步C#端 定义 C#调用 ios 原生函数标识 固定写法

cs 复制代码
 /// <summary>
        /// 定义 C#调用 ios 原生函数标识 固定写法
        /// </summary>
        private const string DLLName = "__Internal";
        [UsedImplicitly, DllImport(DLLName)]
        private static extern void MobileNumberAuthiOS_Initialize(string secret, AliMobileAuthLogCallback logCallback,
            NumberAuthInitCallback initCallback);

第二步C#端 定义c# 传递到原生的的委托代理

cs 复制代码
 /// <summary>
        /// 定义c# 传递到原生的的委托代理,接收ios原生回传的值
        /// </summary>
        private delegate void AliMobileAuthLogCallback(string log);

        private delegate void NumberAuthInitCallback(int success, string msg);

第三步C# 端 定义C#端的代理函数,接收ios 传递过来的值

cs 复制代码
 /// <summary>
        /// 定义C#端的代理函数,用于接收ios 传递过来的值
        /// </summary>
        /// <param name="log"></param>
        [MonoPInvokeCallback(typeof(AliMobileAuthLogCallback))]
        private static void HandleOnAliMobileAuthLogCallback(string log)
        {
            InfoLog(log);
        }

        [MonoPInvokeCallback(typeof(NumberAuthInitCallback))]
        private static void HandleOnSmsAuthInitCallback(int success, string msg)
        {
            InfoLog($"开始初始化回调,success:{success} msg: {msg}");
            _initializeCallback?.Invoke(success, msg);
        }

第四步 C#端 调用上面定的调用ios 的函数

cs 复制代码
  /// C# 调用上面定的调用ios 的函数 ,secret 参数,HandleOnAliMobileAuthLogCallback,HandleOnSmsAuthInitCallback 要传递过去的代理函数
            MobileNumberAuthiOS_Initialize(secret, HandleOnAliMobileAuthLogCallback, HandleOnSmsAuthInitCallback);

第五步 ios 端 ios 定义c#调用的ios 方法 固定写法

objectivec 复制代码
///ios 定义c#调用的ios 方法  固定写法
#if defined(__cplusplus)
extern "C" {
#endif
    void MobileNumberAuthiOS_Initialize(const char* secret ,void(*aliMobileAuthLogCallback)(const char* log), void(*initSDKCallback)(int, const char * )){
        ///将c#的代理指针赋值给ios的块指针
        AliMobileAuthLogCallback = aliMobileAuthLogCallback;
        InitSDKCallback = initSDKCallback;
        ///调用ios的方法
        [[AliMobileNumberAuth sharedManager] Initialize:secret];
    }
    
#if defined(__cplusplus)
}
#endif

第六步ios 端 定义接收c#要传递过来的代理指针

objectivec 复制代码
///定义接收c#要传递过来的代理指针
static void (*AliMobileAuthLogCallback)(const char* log);
static void(*InitSDKCallback)(int,const char *);

第七步ios 端 在ios函数中 回调c#的代码函数,将ios这边的值传递到c#

objectivec 复制代码
-(void)Initialize:(const char*)key {
    ///接收c#传递过来的值
    NSString * dataString  = [NSString stringWithFormat:@"%s",key];
    ///ios 回调c#的代码函数,将ios这边的值传递到c#
    if (InitSDKCallback) {
        NSString * dataString = @"回传值";
        int code = 1;
      InitSDKCallback(code,[dataString UTF8String]);
      }
    
}

以上就是unity和ios 原生交互 通过指针传值和代理(delegate)回传值 定义和接收值的完整实现过程

第八步 C# 和ios 完整代码部分

8.1 ios 代码
objectivec 复制代码
//ios 代码
#import "AliMobileNumberAuth.h"


///定义接收c#要传递过来的代理指针
static void (*AliMobileAuthLogCallback)(const char* log);
static void(*InitSDKCallback)(int,const char *);


static bool EnableLog;
@interface  AliMobileNumberAuth()
@end

@implementation AliMobileNumberAuth

///ios 定义c#调用的ios 方法  固定写法
#if defined(__cplusplus)
extern "C" {
#endif
    void MobileNumberAuthiOS_Initialize(const char* secret ,void(*aliMobileAuthLogCallback)(const char* log), void(*initSDKCallback)(int, const char * )){
        ///将c#的代理指针赋值给ios的块指针
        AliMobileAuthLogCallback = aliMobileAuthLogCallback;
        InitSDKCallback = initSDKCallback;
        ///调用ios的方法
        [[AliMobileNumberAuth sharedManager] Initialize:secret];
    }
    
#if defined(__cplusplus)
}
#endif

-(void)Initialize:(const char*)key {
    ///接收c#传递过来的值
    NSString * dataString  = [NSString stringWithFormat:@"%s",key];
    ///ios 回调c#的代码函数,将ios这边的值传递到c#
    if (InitSDKCallback) {
        NSString * dataString = @"回传值";
        int code = 1;
      InitSDKCallback(code,[dataString UTF8String]);
      }
    
}
#pragma mark - LifeCycle
+(instancetype)sharedManager {
    static dispatch_once_t onceToken;
    static AliMobileNumberAuth *instance;
    dispatch_once(&onceToken, ^{
        instance = [[AliMobileNumberAuth alloc] init];
    });
    return instance;
}
}
8.2 c# 代码
cs 复制代码
using System;
using System.Runtime.InteropServices;
using AOT;
using Bao.Debug;
using JetBrains.Annotations;

namespace Bao.Account.SDK
{
    public class MobileNumberAuthiOS 
    {
        #region 初始化🇭相关

        public static MobileNumberAuthiOS _instance;
        public static  Action<int, string> _initializeCallback;
       
        private Action<bool, string> _heckEnvironmentCallback;
        private Action<bool, string> _getTokenCallback;

        
        /// <summary>
        /// 定义c# 传递到原生的的委托代理,接收ios原生回传的值
        /// </summary>
        private delegate void AliMobileAuthLogCallback(string log);

        private delegate void NumberAuthInitCallback(int success, string msg);

        #endregion

        #region Native Methods
#if UNITY_IOS 
        /// <summary>
        /// 定义 C#调用 ios 原生函数标识 固定写法
        /// </summary>
        private const string DLLName = "__Internal";
        [UsedImplicitly, DllImport(DLLName)]
        private static extern void MobileNumberAuthiOS_Initialize(string secret, AliMobileAuthLogCallback logCallback,
            NumberAuthInitCallback initCallback);
#endif
        #endregion

        private static void InfoLog(string msg)
        {
            LogFile.get.Log($"阿里一键登录, iOS, {msg}");
        }
        
        public void Initialize(string secret, Action<int, string> callback, bool enableLog)
        {
            /// C# 调用上面定的调用ios 的函数 ,secret 参数,HandleOnAliMobileAuthLogCallback,HandleOnSmsAuthInitCallback 要传递过去的代理函数
            MobileNumberAuthiOS_Initialize(secret, HandleOnAliMobileAuthLogCallback, HandleOnSmsAuthInitCallback);
        }
        
        /// <summary>
        /// 定义C#端的代理函数,用于接收ios 传递过来的值
        /// </summary>
        /// <param name="log"></param>
        [MonoPInvokeCallback(typeof(AliMobileAuthLogCallback))]
        private static void HandleOnAliMobileAuthLogCallback(string log)
        {
            InfoLog(log);
        }

        [MonoPInvokeCallback(typeof(NumberAuthInitCallback))]
        private static void HandleOnSmsAuthInitCallback(int success, string msg)
        {
            InfoLog($"开始初始化回调,success:{success} msg: {msg}");
            _initializeCallback?.Invoke(success, msg);
        }

    }
}

private delegate void OnViewClosed(int result, string msg);   // 

[MonoPInvokeCallback(OnViewClosed)]
static void CalledByNativeC(int result, string msg)
{
    // some logic here
}

// ... 

#if UNITY_IPHONE || UNITY_IOS
[DllImport("__Internal")]
private static extern void SetOnViewClosed(OnViewClosed);
#endif

// ...
SetOnViewClosed(CalledByNativeC);    // 把C#中的回调函数传给C

二 、方案二 UnitySendMessage

2.1 使用 UnitySendMessage 时具有以下限制:

1.通过原生代码,只能调用与以下签名对应的脚本方法:void MethodName(string message);。

2.对 UnitySendMessage 的调用是异步的,并有一帧延迟

3.如果两个或多个游戏对象具有相同的名称,则在使用 UnitySendMessage 时可能导致冲突

4.无论使用什么方式调用UnitySendMessage方法,方法最终会使用主线程运行。

2.2 UnitySendMessage 使用方法

UnitySendMessage("[gameobject_name]", "[method_name]", "[string_param]");

这个方法要求场景中有个特定名称的GameObject对象,同时该对象上应该挂载某个MonoBehaviour脚本,在该脚本中包含有一个特定的方法(如下所示),当然如果该对象上挂载了多个脚本,并且这些脚本中都有该方法,那么这些方法都会被调用的!

2.3 iOS 向C# 发送消息

MessageReceiver (MessageReceiver脚本绑定到MessageReceiver该游戏对象上)

cs 复制代码
UnitySendMessage("MessageReceiver", "OnMessageReceived", "Hello from iOS!");
cs 复制代码
using UnityEngine;

public class MessageReceiver : MonoBehaviour
{
    public void OnMessageReceived(string message)
    {
        Debug.Log("Received message from iOS: " + message);
    }
}

2.4 Unity调用iOS原生方法

cs 复制代码
using UnityEngine;
using System.Runtime.InteropServices;

public class NativeMethodCaller : MonoBehaviour
{
    [DllImport("__Internal")]
    private static extern void CallNativeMethod(string message);

    public void CalliOSMethod(string message)
    {
        CallNativeMethod(message);
    }
}

2.5 ios 实现方法

cs 复制代码
extern "C" {
    int CallNativeMethod(const char *msg) {
        
    }
}
相关推荐
梓贤Vigo36 分钟前
【Axure高保真原型】视频列表播放器
交互·产品经理·axure·原型·中继器
Sitarrrr1 小时前
【Unity】ScriptableObject的应用和3D物体跟随鼠标移动:鼠标放置物体在场景中
3d·unity
极梦网络无忧1 小时前
Unity中IK动画与布偶死亡动画切换的实现
unity·游戏引擎·lucene
逐·風9 小时前
unity关于自定义渲染、内存管理、性能调优、复杂物理模拟、并行计算以及插件开发
前端·unity·c#
_oP_i11 小时前
Unity Addressables 系统处理 WebGL 打包本地资源的一种高效方式
unity·游戏引擎·webgl
2401_8658548813 小时前
iOS应用想要下载到手机上只能苹果签名吗?
后端·ios·iphone
小乖兽技术15 小时前
C#与C++交互开发系列(二十):跨进程通信之共享内存(Shared Memory)
c++·c#·交互·ipc
Leoysq19 小时前
【UGUI】实现点击注册按钮跳转游戏场景
游戏·unity·游戏引擎·ugui
_oP_i1 天前
unity中 骨骼、纹理和材质关系
unity·游戏引擎·材质
HackerTom1 天前
iOS用rime且导入自制输入方案
ios·iphone·rime