背景
unity需要調(diào)用其沒(méi)有實(shí)現(xiàn)的原生功能崇猫。
unity使用C#開(kāi)發(fā),可以與c++混編匾委。
iOS使用Objective-c開(kāi)發(fā)拖叙,可以與C++和C混編。
例如:
- 支付赂乐,分享薯鳍,音視頻,但只提供了 iOS 平臺(tái) SDK挨措。
- 優(yōu)秀插件
- 需要通過(guò) Objective-C 調(diào)用 iOS 原生類庫(kù)代碼挖滤。
交互方式
Unity 通過(guò) C 與 iOS 進(jìn)行交互。
Unity 不能直接調(diào)用 C++ 的原因是 C++ 編譯會(huì)有 Name mangling 問(wèn)題运嗜。
Objective-C 可以與 C/C++ 進(jìn)行混編壶辜。使用 C 代碼封裝對(duì)應(yīng)的 Objective-C 代碼,提供給 Unity 使用担租。
unity主動(dòng)調(diào)用鏈:unity(C#) -> C -> iOS(Objective-C)
iOS調(diào)用鏈: unity(C#) -> 注冊(cè)回調(diào)到iOS -> iOS(Objective-C) -> 通過(guò)注冊(cè)的回調(diào)砸民,調(diào)用C -> 調(diào)用unity(C#)
注意:建議 C 函數(shù)名加有特定意義的前綴,避免函數(shù)名沖突。
unity交互部分
核心文件上代碼:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Runtime.InteropServices; // 必須導(dǎo)入
using System
public class MonoPInvokeCallbackAttribute : Attribute // 用于定義C語(yǔ)音回調(diào)的類
{
public MonoPInvokeCallbackAttribute(Type type)
{
}
}
public class BridgeUnityToNative // 定義了一個(gè)類岭参,用以做橋反惕,可自定義
{
protected static BridgeUnityToNative _manager = null;
public static BridgeUnityToNative Instance
{
get
{
if(_manager == null)
{
_manager = new BridgeUnityToNative();
}
return _manager;
}
}
public delegate void CallBack(int res); // 定義回調(diào),如果定義的方法需要有回調(diào)演侯,則必須先定義delegate姿染,才能核心交互代碼中使用
// 核心交互代碼
#if UNITY_IOS
[DllImport("__Internal")] // 固定形式,注冊(cè)TestCallback方法為可調(diào)用的C函數(shù)
private static extern void TestCallback(); // 封裝必須為private, extern需要定義的方法,不然會(huì)報(bào)錯(cuò)
[DllImport("__Internal")]
private static extern void RegistCallback(CallBack callBack); // 封裝必須為private, extern需要定義的方法,不然會(huì)報(bào)錯(cuò)
[AOT.MonoPInvokeCallback(typeof(CallBack))] // 將LogCallback方法秒际,注冊(cè)為回調(diào)
static void LogCallback(int res)
{
Debug.Log("調(diào)用了c# callback" + res);
}
public void TestCallbackFunc(int retCode) // 對(duì)外接口方法悬赏,,外部文件調(diào)用此方法驗(yàn)證demo
{
Debug.Log("調(diào)用了TestCallbackFunc" + retCode);
TestCallback();
RegistCallback(BridgeUnityToNative.LogCallback);
}
#endif
}
上述代碼娄徊,一共定義了兩個(gè)交互函數(shù)闽颇。
無(wú)回調(diào)方法TestCallback
和 有回調(diào)方法RegistCallback
由于作用域的問(wèn)題,兩個(gè)方法都只能private寄锐。所以對(duì)外接口需要用c#包一層
[AOT.MonoPInvokeCallback(typeof(CallBack))]
的下一個(gè)函數(shù)兵多,可以用于回調(diào)代理。其函數(shù)類類型必須與代理完全一致橄仆,否則會(huì)報(bào)錯(cuò)
這里函數(shù)名和回調(diào)類型剩膘,必須要跟iOS(Objective-C)的類型完全一致。不然會(huì)報(bào)錯(cuò)盆顾,無(wú)法調(diào)用整個(gè)函數(shù)怠褐。
注意事項(xiàng):
TestCallback
和'RegistCallback'方法。只在此處extern了方法名椎扬,所以不會(huì)有任何檢查機(jī)制惫搏,C#或iOS改了方法具温,對(duì)方完全察覺(jué)不到蚕涤,驗(yàn)證也很費(fèi)勁。所以精心維護(hù)一份交互文檔是很重要的铣猩。
iOS交互部分
因?yàn)橐霤++ , 所有.m文件的后綴要改成.mm
.h文件:
//
// IOSToUnity.h
// Unity-iPhone
//
// Created by yangda on 2019/1/12.
//
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
#ifndef ConnectUnityToiOS_h
#define ConnectUnityToiOS_h
#endif /* ConnectUnityToiOS_h */
@interface ConnectUnityToiOS : NSObject
typedef void(*CallBack)(int retCode);
+ (ConnectUnityToiOS *)sharedInstance;
extern "C"
{
void TestCallback();
void RegistCallback(CallBack callBack);
}
@end
其中:typedef void(*CallBack)(int retCode);
對(duì)應(yīng)C#代碼中的代理public delegate void CallBack(int res);
定義
核心代碼為:
extern "C"
{
void TestCallback();
void RegistCallback(CallBack callBack);
}
extern "C"
可以擴(kuò)展C函數(shù)揖铜,用于交互
.m文件:
//
// IOSToUnity.m
// Unity-iPhone
//
// Created by yangda on 2019/1/12.
//
#import "ConnectUnityToiOS.h"
@interface ConnectUnityToiOS()
@property(atomic, assign)CallBack callBack;
@end
@implementation ConnectUnityToiOS
// MARK:- OC部分
static ConnectUnityToiOS *instance = nil;
+ (ConnectUnityToiOS *)sharedInstance{
@synchronized(self) {
if(instance == nil) {
instance = [[[self class] alloc] init];
}
}
return instance;
}
- (void)registTestCallBack:(CallBack)callBack {
_callBack = callBack;
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
_callBack(1);
NSLog(@"iOS registTestCallBack");
});
}
// MARK:- C++部分
void TestCallback()
{
NSLog(@"TestCallback");
}
void RegistCallback(CallBack callBack)
{
NSLog(@"iOS RegistCallback");
[ConnectUnityToiOS.sharedInstance registTestCallBack:callBack];
}
@end
如果有錯(cuò)誤的地方歡迎指正