一 、方案一 通过指针传值和使用 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) {
}
}