创建 Android 插件

前言

Android插件是通过挖掘Android平台和生态系统提供的功能来扩展Godot引擎功能的强大工具.

移动游戏货币化就是这样一个例子, 因为它所需要的功能和能力并不属于游戏引擎的核心功能集:

  • 分析

  • 应用内购买

  • 收据验证

  • 安装跟踪

  • 广告

  • 视频广告

  • 交叉推广

  • 游戏中的软硬货币

  • 促销代码

  • A/B 测试

  • 登录

  • 云保存

  • 排行榜和分数

  • 用户支持和反馈

  • 发布到 Facebook、Twitter 等。

  • 推送通知

Android 插件

虽然在Godot 3.2中引入了Android插件系统, 但从Godot 3.2.2开始,Android插件系统得到了重大架构更新. 新的插件系统与之前的插件系统是向后不兼容的, 但在未来发布的3.2.x分支中, 这两个系统都会保留功能. 由于我们之前没有对Android插件系统进行版本更新, 新的插件系统现在被标记为 v1 , 是现代Godot Android生态系统的起点.

注意:在 Godot 4.0 中, 以前的系统将被完全废弃和删除。

作为前提条件, 请确保你了解如何为Android设置一个 自定义构建环境.

Godot Android 插件的核心是一个 Android 归档库aar 归档文件),其注意事项如下:

  • 该库必须依赖Godot引擎库(godot-lib.<version>.<status>.aar). 每一个Godot版本都有一个稳定的版本, 可以在 Godot 下载页面 .

  • 库必须在其清单文件中包含一个专门配置的 <meta-data> 标签.

创建 Android 插件

前提条件: Android Studio 强烈建议作为创建Android插件的IDE使用. 下面的说明假设你使用的是Android Studio.

  1. 按照 这些说明 为你的插件创建一个Android库模块.

  2. 将Godot引擎库作为依赖项添加到插件模块:

  • Godot 下载页下载 Godot 引擎库(godot-lib.<版本>.<状态>.aar,例如 godot-lib.3.4.2.stable.release.aar )。

  • 按照 这些说明 来添加Godot引擎库作为你的插件的依赖.

  • 在插件模块的 build.gradle 文件中, 将Godot引擎库的依赖行 implementation 改为 compileOnly .

  1. 在插件模块中新建一个类,扩展自 org.godotengine.godot.plugin.GodotPlugin。在运行时,会使用这个类来实例化单例对象,供 Godot 引擎来加载、初始化、运行这个插件。

  2. 更新插件 AndroidManifest.xml 文件:

  • 打开插件 AndroidManifest.xml 文件.

  • 如果 <application></application> 不见了, 请添加该标签.

  • <application> 标签中,添加一个 <meta-data> 标签设置,如下所示:

    1. <meta-data
    2. android:name="org.godotengine.plugin.v1.[PluginName]"
    3. android:value="[plugin.init.ClassFullName]" />

    其中 PluginName 是插件的名称, plugin.init.ClassFullName 是插件加载类的全称(包+类名).

  1. 为你的插件添加剩余的逻辑, 并运行 gradlew build 命令来生成插件的 aar 文件. 构建过程中可能会同时生成 debugreleaseaar 文件. 根据你的需要, 只选择一个版本(通常是 release 的版本)提供给你的用户.

    建议 aar 文件名符合以下模式: [PluginName]*.aar 其中 PluginName 是PascalCase中的插件名称(例如: GodotPayment.release.aar ).

  2. 创建一个Godot Android插件配置文件, 帮助系统检测并加载你的插件:

  • 这配置文件必须是 gdap (例如: MyPlugin.gdap).

  • 配置文件格式如下:

    1. [config]
    2. name="MyPlugin"
    3. binary_type="local"
    4. binary="MyPlugin.aar"
    5. [dependencies]
    6. local=["local_dep1.aar", "local_dep2.aar"]
    7. remote=["example.plugin.android:remote-dep1:0.0.1", "example.plugin.android:remote-dep2:0.0.1"]
    8. custom_maven_repos=["http://repo.mycompany.com/maven2"]

    config 部分和字段是必须的, 定义如下:

    • name:插件的名称。

    • binary_type:可以是 localremote。类型影响 binary 字段。

    • binary

      • 如果 binary_typelocal,那么这应该是插件 aar 文件的文件路径。

        • 文件路径可以是相对的(例如: MyPlugin.aar ), 在这种情况下, 它是相对于 res://android/plugins 目录的.

        • 它的文件路径可以是绝对路径:res://some_path/MyPlugin.aar.

      • 如果 binary_typeremote ,那么这应该是一个 remote gradle 二进制 (例如: org.godot.example:my-plugin:0.0.0 )的声明。

  1. `dependencies` 部分和字段是可选的, 定义如下:
  2. - **local** : 包含插件所依赖的本地 `.ar` 二进制文件的文件路径列表. `binary` 字段类似(当 `binary_type` `local` 时), 本地二进制文件的文件路径可以是相对的或绝对的.
  3. - **remote**:包含该插件的远程 Gradle 依赖二进制的列表。
  4. - **custom\_maven\_repos**:包含一个 URL 列表,指定该插件依赖所需的自定义 maven 仓库。

加载和使用 Android 插件

将插件配置文件(例如: MyPlugin.gdap )和(如果有的话)它的本地二进制文件(例如: MyPlugin.aar )和对应的依赖移到Godot项目的 res://android/plugins 目录下.

Godot编辑器会自动解析 res://android/plugins 目录下的所有 .gdap 文件, 并在 Plugins 部分的Android导出预设窗口中显示检测到的可切换插件列表.

../../../_images/android_export_preset_plugins_section.png

从你的脚本中:

  1. if Engine.has_singleton("MyPlugin"):
  2. var singleton = Engine.get_singleton("MyPlugin")
  3. print(singleton.myPluginFunction("World"))

捆绑GDNative资源

Android 插件可以定义并提供 C/C++ GDNative 资源,以提供和/或访问游戏逻辑的功能。GDNative 资源可以被捆绑在插件的 aar 文件中,这简化了分发和部署过程:

  • 定义的GDNative库的共享库( .so )将由 aar 构建系统自动捆绑.

  • Godot *.gdnlib*.gdns 资源文件必须在插件 assets 目录下手动定义. 这些资源相对于 assets 目录的推荐路径应该为 godot/plugin/v1/[PluginName]/ .

对于 GDNative 库,插件单例对象必须覆盖 org.godotengine.godot.plugin.GodotPlugin::getPluginGDNativeLibrariesPaths() 方法,并返回捆绑的 GDNative 库配置文件的路径(*.gdnlib)。这些路径必须是相对于 assets 目录的。在运行时,插件将把这些路径提供给 Godot 核心,核心将使用它们来加载和初始化捆绑的 GDNative 库。

参考实现

故障排除

Godot 在加载时崩溃

检查 adb logcat 是否存在可能的问题,然后:

  • 检查插件暴露的方法是否使用了下列 Java 类型:voidbooleanintfloatjava.lang.Stringorg.godotengine.godot.Dictionaryint[]byte[]float[]java.lang.String[]

  • 暂时不支持更复杂的数据类型.