Godot Android 插件
前言
Android 插件能够利用 Android 平台及其生态系统所提供的功能来扩展 Godot 引擎的功能,是一种强大工具。
例如在 Godot 4 中,不少基于 Android 的 XR 平台就是通过 Android 插件来支持的,无需在核心代码中增加供应商专用代码和二进制文件。
Android 插件
Android 插件系统的第一版(v1)是在 Godot 3 中引入的,与 Godot 4.0 和 4.1 兼容。这个版本能够让开发者使用 Java、Kotlin 和原生功能增强 Godot 引擎。
使用 v1 架构构建的 Android 插件已从 Godot 4.2 开始弃用。Godot 4.2 为 Android 插件引入了全新的第二版(v2)架构。
v2 架构
备注
Godot Android 插件使用 Gradle 构建系统。
与之前的 v1 架构一样,Android 插件仍然是基于 Android 归档库的。
Godot Android 插件 v2 的本质仍然是一个 Android 库,依赖于 Godot Android 库和自定义的 Android 库说明文件。
这个架构能够让 Android 插件通过以下方法扩展功能:
Android 平台 API
Android 库
Kotlin 和 Java 库
原生库(通过 JNI)
GDExtension 库
每个插件都有一个从 GodotPlugin 类扩展而来的 init 类,该类由 Godot Android 库 提供。
GodotPlugin
类提供了访问运行中的Godot实例以及添加钩子到其生命周期。它在运行时由 Godot 引擎加载。
v2 打包格式
v1 Android插件需要一个自定义的 gdap
配置文件,由Godot Editor来检测和加载。然而,这种方法有几个缺点,主要是缺乏灵活性,而且偏离了 现有的 Godot EditorExportPlugin 格式、交付和安装流程 。
这已经通过弃用 gdap
打包和配置机制,并改为使用现有的 Godot EditorExportPlugin
打包格式,解决了 v2 Android 插件的问题。同时,EditorExportPlugin API
也得到了扩展,以正确支持 Android 插件。
构建 v2 Android 插件
一个 GitHub 项目模板 已提供 在 https://github.com/m4gr3d/Godot-Android-Plugin-Template ,以 快速启动构建适用于 Godot 4.2+ 的 Godot Android 插件 。你可以参考 template README 来设置你自己的 Godot Android 插件项目。
为了进一步理解,以下是创建项目模板所使用步骤的详细分解:
按照 这些说明 创建一个Android库模块。
更新模块的
gradle
构建文件,将 Godot Android 库添加为依赖项:dependencies { implementation("org.godotengine:godot:4.2.0.stable") }
Godot Android 库`托管在 MavenCentral <https://central.sonatype.com/artifact/org.godotengine/godot>`_ 上,并在每次发布时更新。
创建 GodotAndroidPlugin,这是一个用于插件的初始化类,扩展自 GodotPlugin。
If the plugin exposes Kotlin or Java methods to be called from GDScript, they must be annotated with @UsedByGodot. The name called from GDScript must match the method name exactly. There is no coercing
snake_case
tocamelCase
. For example, from GDScript:if Engine.has_singleton("MyPlugin"): var singleton = Engine.get_singleton("MyPlugin") print(singleton.myPluginFunction("World"))
如果插件使用了 signals ,则类初始化时必须通过重写 GodotPlugin::getPluginSignals() 方法以返回所使用的信号集。要发射信号,插件可以使用 GodotPlugin::emitSignal(...) 方法。
使用以下元数据更新插件的
AndroidManifest.xml
文件:<meta-data android:name="org.godotengine.plugin.v2.[PluginName]" android:value="[plugin.init.ClassFullName]" />
其中:
PluginName
是插件的名称
plugin.init.ClassFullName
是插件初始化类的完整组件名称(包 + 类名)(例如:org.godotengine.plugin.android.template.GodotAndroidPlugin
)。
创建 EditorExportPlugin 配置来打包插件。创建配置的步骤可以在《打包 v2 Android 插件》章节中看到。
构建带 GDExtension 能力的 v2 Android 插件
与 v1 Android 插件中的 GDNative 支持类似,v2 Android 插件支持集成 GDExtension 功能。
在 https://github.com/m4gr3d/GDExtension-Android-Plugin-Template 提供了一个 github 项目模板,作为为 Godot 4.2+ 构建 GDExtension Android 插件的快速入门。你可以按照模板的 README 来设置你自己的 Godot Android 插件项目。
将 v1 Android 插件迁移至 v2
如果你想要将 v1 Android 插件迁移至 v2,请使用以下步骤:
更新插件的清单文件:
将
org.godotengine.plugin.v1
前缀改为org.godotengine.plugin.v2
更新 Godot Android 库构建依赖:
如果你愿意,你可以继续使用`Godot 的下载页面 <https://godotengine.org/download>`_中的
godot-lib.<version>.<status>.aar
可执行文件。确保它已更新到最新的稳定版本。或者你可以切换到 MavenCentral 提供的依赖项:
dependencies { implementation("org.godotengine:godot:4.2.0.stable") }
更新 Godot Android 库依赖项后,同步或构建插件并解决任何编译错误:
GodotPlugin::getGodot()
提供的Godot
实例不再有权访问android.content.Context
引用。请改用GodotPlugin::getActivity()
。
删除
gdap
配置文件并按照打包 v2 Android 插件章节中的说明设置插件配置。
打包 v2 Android 插件
如前文所述,v2 版本的 Android 插件现在是以 EditorExportPlugin
插件的形式提供给 Godot 编辑器的,所以打包方法也大致相同。
在插件目录(例如
addons/<插件名称>/
)中添加插件输出的二进制文件在插件目录(例如
addons/<插件名称>/
)中添加实现导出功能的工具脚本创建的脚本必须是
@tool
脚本,否则无法正常工作导出工具脚本的作用是对 Android 插件进行配置,并将其加入 Godot 编辑器的导出流程。这个脚本大致应该是这样的:
@tool extends EditorPlugin # A class member to hold the editor export plugin during its lifecycle. var export_plugin : AndroidExportPlugin func _enter_tree(): # Initialization of the plugin goes here. export_plugin = AndroidExportPlugin.new() add_export_plugin(export_plugin) func _exit_tree(): # Clean-up of the plugin goes here. remove_export_plugin(export_plugin) export_plugin = null class AndroidExportPlugin extends EditorExportPlugin: # Plugin's name. var _plugin_name = "<plugin_name>" # Specifies which platform is supported by the plugin. func _supports_platform(platform): if platform is EditorExportPlatformAndroid: return true return false # Return the paths of the plugin's AAR binaries relative to the 'addons' directory. func _get_android_libraries(platform, debug): if debug: return PackedStringArray(["<paths_to_debug_android_plugin_aar_binaries>"]) else: return PackedStringArray(["<paths_to_release_android_plugin_aar_binaries>"]) # Return the plugin's name. func _get_name(): return _plugin_name
这个工具脚本中最常用的 EditorExportPlugin API 如下:
_supports_platform:如果插件支持给定平台,则返回
true
。对于 Android 插件,当platform
为 EditorExportPlatformAndroid 时,必须返回true
_get_android_libraries:检索插件提供的 Android 库二进制文件(AAR 文件)的本地路径
_get_android_dependencies:检索插件提供的 Android maven 依赖项集(例如:org.godot.example:my-plugin:0.0.0)
_get_android_dependencies_maven_repos:检索由
_get_android_dependencies
提供的 android 依赖项的 maven 存储库的 url_get_android_manifest_activity_element_contents:更新生成的 Android 清单中 <activity> 元素的内容
_get_android_manifest_application_element_contents:更新生成的 Android 清单中 <application> 元素的内容
_get_android_manifest_element_contents:更新生成的 Android 清单中 <manifest> 元素的内容
_get_android_manifest_*
方法允许插件自动提供对应用程序清单的更改,这些更改在 Godot 编辑器更新时保留,从而解决了 v1 Android 插件长期存在的问题。
创建一个
plugin.cfg
。这是一个包含有关你的插件的元数据的 INI 文件:[plugin] name="<plugin_name>" description="<plugin_description>" author="<plugin_author>" version="<plugin_version>" script="<relative_path_to_the_export_tool_script>"
作为参考,这里是 Godot Android 插件项目模板的文件夹结构。在构建时,export_scripts_template
目录的内容,以及生成的插件二进制文件,被复制到 addons/<plugin_name>
目录:
export_scripts_template/
|
+--export_plugin.gd # export plugin tool script
|
+--plugin.cfg # plugin INI file
使用 GDExtension 功能打包 v2 Android 插件
对于 GDExtension,我们遵循与打包 v2 Android 插件相同的步骤,并在与 plugin.cfg
相同的位置添加 GDExtension 配置文件。
作为参考,这里是 GDExtension Android 插件项目模板的文件夹结构。在构建时,export_scripts_template
目录的内容以及生成的插件二进制文件将被复制到 addons/<plugin_name>
目录:
export_scripts_template/
|
+--export_plugin.gd # export plugin tool script
|
+--plugin.cfg # plugin INI file
|
+--plugin.gdextension # GDExtension config file
配置文件 plugin.gdextension
看上去是这样的:
[configuration]
entry_symbol = "plugin_library_init"
compatibility_minimum = "4.2"
android_aar_plugin = true
[libraries]
android.debug.arm64 = "res://addons/GDExtensionAndroidPluginTemplate/bin/debug/arm64-v8a/libGDExtensionAndroidPluginTemplate.so"
android.release.arm64 = "res://addons/GDExtensionAndroidPluginTemplate/bin/release/arm64-v8a/libGDExtensionAndroidPluginTemplate.so"
...
需要注意的是这里的 android_aar_plugin
字段,这个字段说明该 GDExtension 模块是以 v2 Android 插件的形式提供的。导出过程中就会告诉 Godot 编辑器,这个 GDExtension 原生共享库是由 Android 插件 AAR 二进制导出的。
对 GDExtension Android 插件而言,插件的初始类必须覆盖 GodotPlugin::getPluginGDExtensionLibrariesPaths(),并且返回所捆绑的 GDExtension 库配置文件的路径(*.gdextension
)。
路径必须相对于 Android 库的 assets
目录。运行时,插件会向 Godot 引擎提供这些路径,用于加载并初始化所捆绑的 GDExtension 库。
使用 v2 Android 插件
备注
要求 Godot 4.2 或更高版本
v2 Android 插件需要使用 Gradle 构建过程。
提供的 github 项目模板包括用于快速测试的演示 Godot 项目。
将插件的输出目录(
addons/<plugin_name>
)复制到目标 Godot 项目的目录在 Godot 编辑器中打开项目;编辑器应该会检测到该插件
导航到
项目
->项目设置...
->插件
,并确保插件已启用通过点击
项目
->安装 Android 构建模板...
来安装 Godot Android 构建模板导航到
项目
->导出...
在
导出
窗口中,创建一个Android 导出预设
在
Android 导出预设
中,滚动到Gradle 构建
,并将使用 Gradle 构建
设置为true
根据需要更新项目的脚本以访问插件的功能。例如:
if Engine.has_singleton("MyPlugin"): var singleton = Engine.get_singleton("MyPlugin") print(singleton.myPluginFunction("World"))
将 Android 设备连接到你的机器并在其上运行该项目
使用 v2 Android 插件作为 Android 库
由于它们也是 Android 库,Godot v2 Android 插件可以从其 EditorExportPlugin
包装中剥离出来,并作为原始 AAR
二进制文件提供,以便与 Godot Android 库一起作为库被 Android 应用程序使用。
如果针对这种用例,请确保包含有关如何包含 AAR
二进制文件的附加说明(例如:Android 应用程序清单的自定义添加)。
参考实现
技巧与指南
简化对暴露的 Java / Kotlin API 的访问
为了更轻松地访问 Godot 编辑器中公开的 Java / Kotlin API,建议为插件用户提供一个(或多个) gdscript 包装器类以供交互。
例如:
class_name PluginInterface extends Object
## Interface used to access the functionality provided by this plugin.
var _plugin_name = "GDExtensionAndroidPluginTemplate"
var _plugin_singleton
func _init():
if Engine.has_singleton(_plugin_name):
_plugin_singleton = Engine.get_singleton(_plugin_name)
else:
printerr("Initialization error: unable to access the java logic")
## Print a 'Hello World' message to the logcat.
func helloWorld():
if _plugin_singleton:
_plugin_singleton.helloWorld()
else:
printerr("Initialization error")
支持在 Godot 编辑器中使用 GDExtension 功能
如果计划在 Godot 编辑器中使用 GDExtension 功能,建议对 GDExtension 的原生二进制文件的编译,不仅要针对 Android ,还要针对开发人员/用户打算在其上运行 Godot 编辑器的操作系统。如果不这样做,可能会阻止开发人员/用户编写从 Godot 编辑器内部访问插件的代码。
这可能涉及为主机操作系统创建虚拟插件,以便将 API 发布给编辑器。你可以使用 godot-cpp-template github 模板来参考如何操作。
Godot 在加载时崩溃
检查 adb logcat
是否存在可能的问题,然后:
检查插件暴露的方法是否使用了下列 Java 类型:
void
、boolean
、int
、float
、java.lang.String
、org.godotengine.godot.Dictionary
、int[]
、byte[]
、float[]
、java.lang.String[]
。暂时不支持更复杂的数据类型.