如何将Swift回调中的参数传递至Unity?
Unity iOS插件异步回调实现方案(Swift+C桥接)
问题背景
我正在用Swift编写Unity的iOS插件,通过C语言做桥接层,目前同步调用逻辑运行正常。现在我有一个带回调的Swift函数,当回调触发时会返回一些值,想把这些值传递到Unity,该怎么实现?
现有同步调用代码
Unity (C#)
public class PluginHelper : MonoBehaviour { [DllImport("__Internal")] private static extern double IOS_getVersion(); private void Start() { double result = IOS_getVersion(); Debug.Log(result); } }
C桥接层
#import <Foundation/Foundation.h> #include "UnityFramework/UnityFramework-Swift.h" extern "C" { double IOS_getVersion(){ double result = [[UnityPlugin shared] swift_getVersion]; return result; } }
Swift插件类
@objc public class UnityPlugin : NSObject { @objc public static let shared = UnityPlugin() @objc public func swift_getVersion() -> Double{ // 原有逻辑 let result = 1.0 // 示例值 return result } }
待处理的带回调Swift函数
public static func swiftfunction(target: AnyObject, handler: @escaping ((Notification?) -> Void)) -> NSObjectProtocol
异步回调实现步骤
1. 修改Swift代码,适配Unity回调
通过Unity官方提供的UnitySendMessageC接口实现跨语言消息传递,同时处理回调数据和内存管理:
@objc public class UnityPlugin : NSObject { @objc public static let shared = UnityPlugin() private var notificationObserver: NSObjectProtocol? // 保存Unity接收消息的GameObject名称和方法名 private var unityCallbackObjName: String? private var unityCallbackMethodName: String? @objc public func swift_getVersion() -> Double{ let result = 1.0 // 示例值 return result } // 新增:注册回调的方法,接收Unity的对象名和方法名 @objc public func registerNotificationCallback(gameObjName: String, methodName: String) { self.unityCallbackObjName = gameObjName self.unityCallbackMethodName = methodName // 调用带回调的swiftfunction notificationObserver = UnityPlugin.swiftfunction(target: self) { [weak self] notification in guard let self = self, let objName = self.unityCallbackObjName, let methodName = self.unityCallbackMethodName else { return } // 解析通知内容(示例:取userInfo中的"value"字段) let callbackValue = notification?.userInfo?["value"] as? String ?? "no data" // 调用UnitySendMessage向Unity发送消息 UnitySendMessage(objName, methodName, callbackValue) } } // 新增:移除观察者,避免内存泄漏 @objc public func unregisterNotificationCallback() { if let observer = notificationObserver { NotificationCenter.default.removeObserver(observer) notificationObserver = nil unityCallbackObjName = nil unityCallbackMethodName = nil } } } // 声明UnitySendMessage函数,让Swift可以调用 func UnitySendMessage(_ obj: UnsafePointer<CChar>, _ method: UnsafePointer<CChar>, _ msg: UnsafePointer<CChar>)
2. 更新C桥接层,添加注册/注销回调函数
新增供Unity调用的C接口,实现字符串格式转换:
#import <Foundation/Foundation.h> #include "UnityFramework/UnityFramework-Swift.h" extern "C" { double IOS_getVersion(){ double result = [[UnityPlugin shared] swift_getVersion]; return result; } // 注册回调:接收Unity的GameObject名称和方法名 void IOS_registerNotificationCallback(const char* gameObjName, const char* methodName) { NSString* objName = [NSString stringWithUTF8String:gameObjName]; NSString* method = [NSString stringWithUTF8String:methodName]; [[UnityPlugin shared] registerNotificationCallback:objName methodName:method]; } // 注销回调 void IOS_unregisterNotificationCallback() { [[UnityPlugin shared] unregisterNotificationCallback]; } }
3. 修改Unity C#代码,接收异步回调
添加注册回调的调用逻辑,以及接收回调的处理方法:
using UnityEngine; using System.Runtime.InteropServices; public class PluginHelper : MonoBehaviour { [DllImport("__Internal")] private static extern double IOS_getVersion(); [DllImport("__Internal")] private static extern void IOS_registerNotificationCallback(string gameObjName, string methodName); [DllImport("__Internal")] private static extern void IOS_unregisterNotificationCallback(); private void Start() { // 同步调用示例 double result = IOS_getVersion(); Debug.Log(result); // 注册异步回调:传入当前GameObject名称和接收方法名 IOS_registerNotificationCallback(gameObject.name, "OnNotificationCallbackReceived"); } // 接收iOS回调的方法(必须public,参数类型与Swift传递的一致) public void OnNotificationCallbackReceived(string callbackData) { Debug.Log("收到iOS回调数据:" + callbackData); // 此处添加自定义数据处理逻辑 } // 对象销毁时注销回调,避免内存泄漏 private void OnDestroy() { IOS_unregisterNotificationCallback(); } }
关键说明
- UnitySendMessage:Unity官方提供的跨语言通信接口,参数依次为接收消息的GameObject名称、对象上的方法名、传递的字符串参数;如需传递复杂数据,可序列化为JSON字符串,在Unity端反序列化。
- 内存管理:Swift中需在合适时机移除通知观察者,Unity端在对象销毁时调用注销函数,避免内存泄漏。
- 数据兼容性:确保Swift传递的参数类型与Unity接收方法的参数类型一致,如需传递非字符串数据,需做格式转换。
内容的提问来源于stack exchange,提问作者Gorka C
相关产品推荐
相关产品推荐

