Unity 與 iOS 使用委托通信

Unity攤

從原生代碼回調 C
Unity iOS 支持有限的原生到托管回調功能卦绣。有兩種方式可以做到這一點:

使用 UnitySendMessage
通過委托

使用 UnitySendMessage

此選項更簡單端礼,但有一些限制岗屏。如下所示:

UnitySendMessage("GameObjectName1", "MethodName1", "Message to send");
有三個參數(shù):
目標 GameObject 的名稱
用于調用該對象的腳本方法
用于傳遞給被調用方法的消息字符串

使用 UnitySendMessage 時具有以下限制:

  1. 通過原生代碼淤翔,只能調用與以下簽名對應的腳本方法:void MethodName(string message);蕴茴。
  2. 對 UnitySendMessage 的調用是異步的玉罐,并有一幀延遲。
  3. If two or more GameObjects have the same name, this can cause conflicts when you use UnitySendMessage.

使用委托

當使用委托時岳锁,C# 端的方法必須是靜態(tài)的绩衷,并且必須用 MonoPInvokeCallback 屬性進行標記。必須將該方法作為委托傳遞給在原生代碼中作為函數(shù)實現(xiàn)的 extern 方法激率,這個函數(shù)采用一個指針咳燕,而指針則指向具有對應簽名的函數(shù)。然后乒躺,原生代碼中的函數(shù)指針再引回 C# 靜態(tài)方法招盲。

以上信息來源于 Untiy官方

-----------------------------這是一條分割線-----------------------------

實現(xiàn)目的: 支付或者原生SDK回調(等) 返回時 需要通知Unity側做出響應, 這里我們就需要先從Unity(注冊)傳遞一堆函數(shù)指針(委托)到OC, OC端將它們保存到內存中, 在合適的時機進行調用, 從而回傳到Unity;

為了更方便的使用, 我們將其封裝成靜態(tài)庫;

靜態(tài)庫結構

具體實現(xiàn):

1. Xcode->New Project->Static Library -> Project Name User-defined
image.png

UnityMessageCenter.h

//
//  UnityMessageCenter.h
//  UnityMessageCenter
//
//  Created by jens on 2022/3/16.
//

#import <Foundation/Foundation.h>

#if defined (__cplusplus)
extern "C"
{
#endif

typedef void (*MessageResultHandler) (int arg1, int arg2, const char * content);


#if defined (__cplusplus)
}
#endif


@interface UnityMessageCenter : NSObject

@property(nonatomic, retain) NSMutableDictionary *mMessageDic;

+(UnityMessageCenter*)shareInstance;

-(BOOL)sendMessageToUnityWithMessageId:(NSString *)messageId arg1:(int)arg1 arg2:(int)arg2 content:(NSString *)content;

@end

UnityMessageCenter.m

//
//  UnityMessageCenter.m
//  UnityMessageCenter
//
//  Created by jens on 2022/3/16.
//

#import "UnityMessageCenter.h"

@implementation UnityMessageCenter

typedef void (^MessageResultHandlerTemp) (int arg1, int arg2, const char * content);

@synthesize mMessageDic;


+(NSString*) CreateString:(const char* )str{
    if (str){
        return [NSString stringWithUTF8String:str];
    }
    return [NSString stringWithUTF8String:""];
}

+(UnityMessageCenter*)shareInstance{
    static dispatch_once_t onceToken;
    static UnityMessageCenter* instance = nil;
    dispatch_once(&onceToken, ^{
        instance = [[UnityMessageCenter alloc]init];
        instance.mMessageDic =  [NSMutableDictionary dictionary];
    });
    return instance;
}

-(BOOL)sendMessageToUnityWithMessageId:(NSString *)messageId arg1:(int)arg1 arg2:(int)arg2 content:(NSString *)content{
    MessageResultHandlerTemp handler = [self.mMessageDic objectForKey:messageId];
    if (content ==nil) {
        content= @"";
    }
    if(handler!=nil){
        handler(arg1,arg2, content.UTF8String);
        return YES;
    }
    return NO;
}

@end


#if defined (__cplusplus)
extern "C"
{
#endif
    void RegisterDelegateToIOS (const char * messageId,  MessageResultHandler resultHandler){
        UnityMessageCenter *msg = [UnityMessageCenter shareInstance];
        NSString *msgId = [UnityMessageCenter CreateString:messageId];
        MessageResultHandlerTemp temp =^void(int a,int b,const char *c){
            return resultHandler(a,b,c);
        };
        [msg.mMessageDic setValue:temp  forKey:msgId];
    }
    
#if defined (__cplusplus)
}
#endif

C# .CS腳本代碼

        [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
        public delegate void MessageResultHandler(int arg1, int arg2, string messageContent);
        
#if UNITY_IOS
        [DllImport ("__Internal")]
        static extern void RegisterDelegateToIOS (string messageId, IntPtr resultHandler);
#endif

        public void RegisterMessageHandler(string messageId, MessageResultHandler callback)
        {
#if UNITY_IOS
            IntPtr fp = Marshal.GetFunctionPointerForDelegate(callback);
            RegisterDelegateToIOS(messageId,fp);
#endif
        }

[UnmanagedFunctionPointer(CallingConvention.Cdecl)] : 表面這個委托不受C#管理, 即非托管內存, 詳細參考: 托管和非托管
CallConvention(調用約定):決定函數(shù)參數(shù)傳送時入棧和出棧的順序,Cdecl表示由調用方把參數(shù)出棧嘉冒。

[DllImport ("__Internal")]: 表示函數(shù)位于__Internal.Dll中, 固定寫法曹货。

[MonoPInvokeCallback] : 標記方法是由C或者C++來調用的咆繁。

Marshal.GetFunctionPointerForDelegate() : 獲取函數(shù)指針。

需要注意的是:
1. C中一定要有block與C#中的代理對應;
2. OC字典只能存儲非nil對象;

typedef void (*MessageResultHandler) (int arg1, int arg2, const char * content);

public delegate void MessageResultHandler(int arg1, int arg2, string messageContent);

最后編譯Xcode生成libUnityMessageCenter.a 和 UnityMessageCenter.h頭文件, 拿到其它OC代碼即可使用;

具體使用參考示例:


#import "UnityMessageCenter.h"

 [[UnityMessageCenter shareInstance] sendMessageToUnityWithMessageId:OnInitialized arg1:0 arg2:0 content:@""];

參考博客(感謝):

http://www.reibang.com/p/f01c7e3f666c

https://docs.unity3d.com/cn/2020.3/Manual/PluginsForIOS.html

https://zhuanlan.zhihu.com/p/137970936

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末顶籽,一起剝皮案震驚了整個濱河市玩般,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌礼饱,老刑警劉巖坏为,帶你破解...
    沈念sama閱讀 206,602評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異镊绪,居然都是意外死亡匀伏,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,442評論 2 382
  • 文/潘曉璐 我一進店門镰吆,熙熙樓的掌柜王于貴愁眉苦臉地迎上來帘撰,“玉大人,你說我怎么就攤上這事万皿〈菡遥” “怎么了?”我有些...
    開封第一講書人閱讀 152,878評論 0 344
  • 文/不壞的土叔 我叫張陵牢硅,是天一觀的道長蹬耘。 經(jīng)常有香客問我,道長减余,這世上最難降的妖魔是什么综苔? 我笑而不...
    開封第一講書人閱讀 55,306評論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮位岔,結果婚禮上如筛,老公的妹妹穿的比我還像新娘。我一直安慰自己抒抬,他們只是感情好杨刨,可當我...
    茶點故事閱讀 64,330評論 5 373
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著擦剑,像睡著了一般妖胀。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上惠勒,一...
    開封第一講書人閱讀 49,071評論 1 285
  • 那天赚抡,我揣著相機與錄音,去河邊找鬼纠屋。 笑死涂臣,一個胖子當著我的面吹牛,可吹牛的內容都是我干的售担。 我是一名探鬼主播赁遗,決...
    沈念sama閱讀 38,382評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼闯估,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了吼和?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 37,006評論 0 259
  • 序言:老撾萬榮一對情侶失蹤骑素,失蹤者是張志新(化名)和其女友劉穎炫乓,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體献丑,經(jīng)...
    沈念sama閱讀 43,512評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡末捣,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 35,965評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了创橄。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片箩做。...
    茶點故事閱讀 38,094評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖妥畏,靈堂內的尸體忽然破棺而出邦邦,到底是詐尸還是另有隱情,我是刑警寧澤醉蚁,帶...
    沈念sama閱讀 33,732評論 4 323
  • 正文 年R本政府宣布燃辖,位于F島的核電站,受9級特大地震影響网棍,放射性物質發(fā)生泄漏黔龟。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,283評論 3 307
  • 文/蒙蒙 一滥玷、第九天 我趴在偏房一處隱蔽的房頂上張望氏身。 院中可真熱鬧,春花似錦惑畴、人聲如沸蛋欣。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,286評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽豁状。三九已至,卻和暖如春倒得,著一層夾襖步出監(jiān)牢的瞬間泻红,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,512評論 1 262
  • 我被黑心中介騙來泰國打工霞掺, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留谊路,地道東北人。 一個月前我還...
    沈念sama閱讀 45,536評論 2 354
  • 正文 我出身青樓菩彬,卻偏偏與公主長得像缠劝,于是被迫代替她去往敵國和親潮梯。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 42,828評論 2 345

推薦閱讀更多精彩內容