Version: 2021.1
优化物理性能
准备应用程序进行应用内购 (IAP)

构建适用于 iOS 的插件

本页介绍如何构建适用于 iOS 平台的原生代码插件

构建适用于 iOS 且包含原生插件的应用程序

要构建适用于 iOS 且包含原生插件的应用程序,请遵循以下步骤:

  1. 对于要调用的每个原生函数,在 C# 文件中定义一个 extern 方法,如下所示:

    [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 编写的插件不需要此声明,因为这些语言不存在名称错用。

通过 C# 使用插件

仅当 iOS 原生插件部署在了实际设备上时,您的应用程序才能调用这些插件,因此应该使用额外的 C# 代码层来封装所有原生代码方法。此代码应使用 UNITY_IOS && !UNITY_EDITOR 条件编译,或者检查 Application.platform,并仅当应用程序在设备上运行时才调用原生方法。最简单的实现方式是:

void MyMethod()
{
# if UNITY_IOS && !UNITY_EDITOR
    CallNativeMethodImplementation();
# else
    CallEditorMethodImplementation();
# endif
}

有关更详细的实现方法,请参阅下面的 Bonjour 浏览器示例 (Bonjour Browser Sample)。

从原生代码回调 C

Unity iOS 支持有限的原生到托管回调功能。有两种方式可以做到这一点: * 使用 UnitySendMessage * 通过委托

使用 UnitySendMessage

此选项更简单,但有一些限制。如下所示:

UnitySendMessage("GameObjectName1", "MethodName1", "Message to send");

有三个参数: * 目标 GameObject 的名称 * 用于调用该对象的脚本方法 * 用于传递给被调用方法的消息字符串

使用 UnitySendMessage 时具有以下限制:

  1. 通过原生代码,只能调用与以下签名对应的脚本方法:void MethodName(string message);
  2. UnitySendMessage 的调用是异步的,并有一帧延迟。
  3. 如果两个或多个游戏对象具有相同的名称,则在使用 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 支持自动插件集成,并且如果在 Plugin Inspector 窗口中为 iOS 启用了文件扩展名,则会将具有以下扩展名的所有文件复制到生成的 Xcode 项目中:.a.m.mm.c.cpp.h。如果具有这些扩展名的任何文件位于 Assets/Plugins/iOS 文件夹中,则 Unity 仅在 iOS 平台上启用这些扩展名。

注意:将文件复制到生成的 Xcode 项目后,它们不再链接到 Unity 项目中的对应文件。如果在 Xcode 中更改了这些文件,必须将它们复制回到您的 Unity 项目中。否则,在下次构建项目时,Unity 将覆盖它们。

此 Inspector 窗口显示已经为 iOS 启用该插件。
此 Inspector 窗口显示已经为 iOS 启用该插件。

有关 iOS 的提示:

  1. 在 iOS 上,托管到非托管的调用是很耗资源的处理器密集型操作。尽量避免每帧调用多个原生方法。

  2. 应使用额外的 C# 层来封装原生方法,该层将调用设备上的原生代码并在 Editor 中返回虚拟值。

  3. 从原生方法返回的字符串值应该是 UTF–8 编码并在堆上分配。Mono 编组调用对于这样的字符串是无成本的。

Bonjour 浏览器示例

可在下面下载一个演示如何使用原生代码插件的简单示例:Bonjour 浏览器示例

此示例演示了如何从 Unity iOS 应用程序调用 Objective-C 代码。该应用程序实现了一个简单的 Bonjour 客户端,并包含:

  • 一个 Unity iOS 项目,其中的 Plugins\Bonjour.cs 是原生代码的 C# 接口,BonjourTest.cs 是实现应用程序逻辑的脚本
  • 原生代码(位于 Assets/Plugins/iOS 中),如上文自动插件集成部分所述,应将此代码添加到构建的 Xcode 项目中
优化物理性能
准备应用程序进行应用内购 (IAP)