本页介绍如何构建适用于 iOS 平台的原生代码插件。
要构建适用于 iOS 且包含原生插件的应用程序,请遵循以下步骤:
1.对于要调用的每个原生函数,在 C# 文件中定义一个 extern 方法,如下所示:
```csharp
[DllImport ("__Internal")]
private static extern float FooPluginFunction();
```
2.将原生代码源文件添加到 Unity 项目中。
3.在 Plugin Inspector 窗口中自定义插件的设置。例如,如果原生代码是特定于 iOS,请确保仅为 iOS 启用该插件。
注意:如果使用 C++ (.cpp) 或 Objective-C++ (.mm) 来实现该插件,则必须使用 C 链接来声明函数以免发生名称错用问题:
extern "C" {
float FooPluginFunction();
}
用 C 或 Objective-C 编写的插件不需要此声明,因为这些语言不存在名称错用。
仅当 iOS 原生插件部署在了实际设备上时,您的应用程序才能调用这些插件,因此应该使用额外的 C# 代码层来封装所有原生代码方法。此代码应使用 UNITY_IOS && !UNITY_EDITOR
条件编译,或者检查 Application.platform
,并仅当应用程序在设备上运行时才调用原生方法。最简单的实现方式是:
void MyMethod()
{
# if UNITY_IOS && !UNITY_EDITOR
CallNativeMethodImplementation();
# else
CallEditorMethodImplementation();
# endif
}
For a more detailed implementation, download the Bonjour Browser sample below.
Unity iOS 支持有限的原生到托管回调功能。有两种方式可以做到这一点:
UnitySendMessage
UnitySendMessage
此选项更简单,但有一些限制。如下所示:
UnitySendMessage("GameObjectName1", "MethodName1", "Message to send");
有三个参数:
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# 端的方法必须是静态的,并且必须用 MonoPInvokeCallback
属性进行标记。必须将该方法作为委托传递给在原生代码中作为函数实现的 extern 方法,这个函数采用一个指针,而指针则指向具有对应签名的函数。然后,原生代码中的函数指针再引回 C# 静态方法。
该方法的 C# 代码如下所示:
delegate void MyFuncType();
[AOT.MonoPInvokeCallback(typeof(MyFuncType))]
static void MyFunction() { }
static extern void RegisterCallback(MyFuncType func);
然后,接受回调的 C 代码如下所示:
typedef void (*MyFuncType)();
void RegisterCallback(MyFuncType func) {}
Unity supports automated plug-in integration and copies all files with the following extensions to the generated Xcode project if you enable them for iOS in the Plugin Inspector window: .a
, .m
, .mm
, .c
, .cpp
, .h
. If any files with these extensions are located in the Assets/Plugins/iOS
folder, Unity only enables them for the iOS platform.
注意:将文件复制到生成的 Xcode 项目后,它们不再链接到 Unity 项目中的对应文件。如果在 Xcode 中更改了这些文件,必须将它们复制回到您的 Unity 项目中。否则,在下次构建项目时,Unity 将覆盖它们。
1.在 iOS 上,托管到非托管的调用是很耗资源的处理器密集型操作。尽量避免每帧调用多个原生方法。
2.应使用额外的 C# 层来封装原生方法,该层将调用设备上的原生代码并在 Editor 中返回虚拟值。
3.从原生方法返回的字符串值应该是 UTF–8 编码并在堆上分配。Mono 编组调用对于这样的字符串是无成本的。
可在下面下载一个演示如何使用原生代码插件的简单示例:Bonjour 浏览器示例。
This example demonstrates how you can invoke Objective-C code from a Unity iOS application. This application implements a simple Bonjour client and consists of:
Plugins\Bonjour.cs
是原生代码的 C# 接口,BonjourTest.cs
是实现应用程序逻辑的脚本Assets/Plugins/iOS
中),如上文自动插件集成部分所述,应将此代码添加到构建的 Xcode 项目中