0%

Unity 游戏调用 iOS 方法

在 Unity 项目中,游戏调用平台原生的功能是很常见的。Android 平台参考Unity 游戏调用 Android 方法

C# 调用 iOS 代码

在 C# 中定义 extern 方法,代码中即可直接调用此方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// 普通方法
[DllImport("__Internal")]
private static extern void func();

// 以字符串当参数的方法
[DllImport("__Internal")]
private static extern void funcWithParam(string param);

// 返回字符串的方法
[DllImport("__Internal")]
private static extern string getStringFunc();

// 返回 int 的方法
[DllImport("__Internal")]
private static extern int getIntFunc();

Xcode 中在 C(.c) 或 Objective-C(.m) 中声明对应的 C 语言方法。如果是 Objective-C(.m) 文件,需要修改后缀为 Objective-C++(.mm) 。例如上述的函数:

1
2
3
4
void func();
void funcWithParam(char *param);
char *getStringFunc();
int getIntFunc();

如果是 C++(.cpp) 或 Objective-C++(.mm) 文件,需要加上 extern "C" 来声明。例如:

1
2
3
4
5
6
extern "C" {
void func();
void funcWithParam(char *param);
char *getStringFunc();
int getIntFunc();
}

iOS 调用 C# 代码

使用 UnitySendMessage

使用 UnitySendMessage 方法来向 Unity 发送消息。

Objective-C 代码:

1
2
3
4
const char *obj = "iOSTestCallback"; // 游戏对象的名称
const char *method = "OniOSCallback"; // 对象的方法
const char *msg = "msg to send"; // 要发的消息
UnitySendMessage(obj, method, msg);

在 Unity 中创建一个游戏对象(GameObject)名为 iOSTestCallback,上面挂载了 iOSTestCallback.cs 脚本,如图:

iOSTestCallback.cs 脚本中实现 OniOSCallback 方法,方法签名必须是 void methodName(string msg)

1
2
3
4
5
6
7
public class iOSTestCallback : MonoBehaviour
{
// 回调的方法 msg 为发送的消息
public void OniOSCallback(string msg)
{
}
}

回调是异步的,在下一帧中执行。

使用委托

在 C# 中定义一个静态(static)方法,并添加 MonoPInvokeCallback 属性。然后将这个方法以函数指针的方式传递给 C 方法。

例如,C# 中代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
delegate void MyFuncType(); // 回调函数的类型

[AOT.MonoPInvokeCallback(typeof(MyFuncType))] // MyFunction 是 MyFuncType 类型的
static void MyFunction() {} // 回调函数

// 将 MyFuncType 类型的 func 传递给 iOS
[DllImport("__Internal")]
private static extern void RegisterCallback(MyFuncType func);

// 调用时,将 MyFunction 作为参数传入
void test()
{
RegisterCallback(MyFunction);
}

Objective-c 代码:

1
2
3
4
typedef void (*MyFuncType)(); // 定义一个函数指针类型
void RegisterCallback(MyFuncType func) {
func(); // 回调到 C#
}

iOS 提示

  • 调用 iOS 原生代码是 CPU 密集型操作,应该避免在一帧内多次调用。
  • C# 层建议封装 iOS 原生代码,并返回虚拟值。
  • iOS 层返回的 string 类型应该是 UTF-8 编码,并在堆上分配内存。C# 会进行内存释放。

例如:返回字符串类型的方法必须是 char * 并在堆上分配内存 ,不能是 const char *,虽然编译可以通过,但是运行时会崩溃,因为 Unity 会对返回的字符串进行释放:

1
2
3
4
5
6
7
8
9
10
11
// 错误
const char *getStringFunc() {
return "test";
}

// 正确
char *getStringFunc() {
char *ret = (char*)malloc(sizeof(char)*128);
strcpy(ret, "test");
return ret;
}

参考链接