在unity开发或者sdk开发经常遇到unity与移动端原生层之间进行通信,这里把它们之间通信做一个整理。
关于Unity与Android之间通信,参考【Unity3d】Unity与Android之间通信
Unity调用Objective-C
主要分三个步骤:
(一)、在xcode中定义要被unity调用的函数
新建一个类,名字可以任意,比如UnityBridge:
头文件:UnityBridge.h
(头文件中不需要字段和函数声明)
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@interface UnityBridge : NSObject
@end
NS_ASSUME_NONNULL_END
头文件里没什么代码,主要代码在实现文件中。
实现文件:UnityBridge.m
实现文件中需要用c语言定义函数,这些函数定义了之后,就可以被unity调用:
#import "UnityBridge.h"
//如果c#调用oc函数时需要一个回调,需要先声明回调参数类型:
typedef void (*MyResultCallback) (int status,const char *result);
#if defined (__cplusplus)
extern "C"
{
#endif
//这里写被unity调用的函数
void test1(void){
//这里是函数实现,支持oc语法
}
/**
* int类型参数,返回int
*/
int test2(int params){
//这里是函数实现,支持oc语法
}
/**
* 字符串类型参数
*/
void test3(const char *params){
//这里是函数实现,支持oc语法
}
/**
* 支持回调参数
*/
void test4(MyResultCallback callback){
//这里是函数实现,支持oc语法
int code = 0;
NSString p = @"test";
const char *result = [p UTF8String];
//回调给c#
callback(code,result)
}
#if defined (__cplusplus)
}
#endif
注意这些代码不要写在@implementation
中,它是c语言的函数。
#if defined (__cplusplus)
这是一个宏判断,因为oc是支持c++,所以这个宏判断肯定是通过的,extern "C"
表示后面函数是c语言的,供外部调用的。
(二)、将oc代码复制到unity工程中。
将oc代码(包括.h和.m源文件)拷贝到Unity工程的Assets
目录或子目录中。
实际上将oc代码放在unity工程的Assets
目录下的任意位置都可以,oc代码会自动被unity引擎识别。
(笔者使用的unity版本是2019.4,以前的版本不知道是否可以是任意位置。)
为了方便管理,oc代码一般放在Assets/Plugins/iOS
中。
(三)、在unity的c#脚本中声明外部(oc)函数原型
using System.Runtime.InteropServices; //需要引入这个命名空间,会提示引入
using UnityEngine;
public class Test
{
private Test() {}
#if UNITY_IOS //加个宏比较好
//以下是外部函数声明,函数签名必须与oc函数保持一致,参数类型用各自语言的,类型映射见文末。
//声明无参数无返回值的函数
[DllImport("__Internal")]
private static extern void test1();
//声明有一个int参数和int返回值的函数
[DllImport("__Internal")]
private static extern int test2(int p);
//声明一个string参数的函数
[DllImport("__Internal")]
private static extern void test3(string p);
//如果需要oc的回调,声明一个回调函数类型
delegate void MyResultDelegate(int code,string result);
[DllImport("__Internal")]
private static extern void test4(MyResultDelegate resultDelegate);
/**
* 回调函数的实现(或者叫实例)
* 注意:必须是static类型的
*/
[AOT.MonoPInvokeCallback(typeof(MyResultDelegate))]
private static void MyResultDelegateInstance(int code, string result)
{
//这里写接收到oc回调的代码
}
#endif
public void CallOC()
{
#if UNITY_IOS
test1();
test2(1);
test3("abc");
test4(MyResultDelegateInstance);
#endif
}
}
在c#中调用oc中对应的方法,参见以上 CallOC()
。
c#调用oc注意事项:
1、数据类型需要使用各自语言的,两者数据类型映射关系在文未。
2、c#中声明的oc方法、回调,都需要static修饰。
Objective-C调用Unity(c#)
oc调用c#比较简单,一般使用以下这个方法:
UnitySendMessage("MyTestObject", "TestFunc", "msg");
UnitySendMessage
函数声明在UnityFramework.framework
中UnityInterface.h
头文件中:
void UnitySendMessage(const char* obj, const char* method, const char* msg);
第一个参数obj表示unity中物体GameObject的名字,注意不是c#脚本的名称也不是类名。
如下图:
第二个参数method表示这个物体挂载的c#脚本中方法的名字。
第三个参数表示msg表示这个方法接收的数据。
例如,以上物体MyTestObject
挂载了MyScript.c#
脚本(如上图),MyScript.c#
中有TestFunc
方法:
using UnityEngine;
public class MyScript : MonoBehaviour
{
private void TestFunc(string content)
{
//这里是接收oc调用的实现
}
}
那么在oc中调用UnitySendMessage("MyTestObject", "TestFunc", "msg")
c#的TestFunc
方法就会执行。
如果有多个参数需要发送,推荐使用json格式。
oc调用c#注意事项:
1、需要依赖UnityFramework.framework
框架。
2、unity工程导出的xcode工程默认已经有UnityFramework.framework
。
3、如果是自己新建的xcode工程需要手动导入这个框架。
附:c#与oc数据类型映射:
Unity(c#) | Objective-C |
---|---|
int | int |
float | float |
bool | bool |
string | const char * |
long | long long |