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) {
        
    }
}
相关推荐
梓贤Vigo1 小时前
【Axure高保真原型】计时秒表
交互·产品经理·axure·原型·中继器
/**书香门第*/4 小时前
Laya ios接入goole广告,搭建环境 1
ios
m0_748256345 小时前
QWebChannel实现与JS的交互
java·javascript·交互
超龄魔法少女9 小时前
[Unity] ShaderGraph动态修改Keyword Enum,实现不同效果一键切换
unity·技术美术·shadergraph
蔗理苦10 小时前
2024-12-24 NO1. XR Interaction ToolKit 环境配置
unity·quest3·xr toolkit
花生糖@10 小时前
Android XR 应用程序开发 | 从 Unity 6 开发准备到应用程序构建的步骤
android·unity·xr·android xr
wakangda10 小时前
React Native 集成 iOS 原生功能
react native·ios·cocoa
向宇it10 小时前
【从零开始入门unity游戏开发之——unity篇02】unity6基础入门——软件下载安装、Unity Hub配置、安装unity编辑器、许可证管理
开发语言·unity·c#·编辑器·游戏引擎
向宇it14 小时前
【从零开始入门unity游戏开发之——unity篇01】unity6基础入门开篇——游戏引擎是什么、主流的游戏引擎、为什么选择Unity
开发语言·unity·c#·游戏引擎
向宇it20 小时前
【从零开始入门unity游戏开发之——C#篇26】C#面向对象动态多态——接口(Interface)、接口里氏替换原则、密封方法(`sealed` )
java·开发语言·unity·c#·游戏引擎·里氏替换原则