相关的官方文档有两篇:
- Creating Android modules
- Compiling for Android
自定义安卓模块好处是,可以扩展 Godot 在安卓系统上的能力。通常游戏开发者会接入游戏平台,或者接入社交平台,进行快速注册、登录和分享,这如此常见,所以,这篇文章意图叙述 Godot 开发自定义安卓模块的整个过程,帮助大家快速达成目的。
一、入口
请将自定义模块目录,放置到
Godot源码\modules
下
必须继承 Godot.SingletonBase
类,做为游戏引擎访问模块的入口。根据命名可知,这是个单例类,所以还得有可以全局访问的成员方法。
package org.godotengine.godot;
public class MyCustomModule extends Godot.SingletonBase {
// 保存 MainActivity 对象
private Activity activity;
/**
* 必要,提供单例全局访问能力
* @param Activity 在 Godot 引擎访问时,会传入 MainActivity 实例
*/
static public Godot.SingletonBase initialize(Activity p_activity) {
return new MyCustomModule(p_activity);
}
/**
* 必要,构造单例对象
* @param Activity Main activity
*/
public MyCustomModule(Activity activity) {
// 注册模块到引擎,param1:模块名称,与类名一致;param2:导出方法,定义则必须实现
registerClass("MyCustomModule", new String[] { "init", "login", });
this.activity = activity;
Log.d(Config.TAG, "Create MyCustomModule instance");
}
// 选用,与 registerClass 传参一致,实现导出方法:init
void init() {
// 例如:初始化三方平台SDK……
}
// 选用,与 registerClass 传参一致,实现导出方法:login
void login() {
}
// 选用,以下回调函数可按照自身需求选择使用
protected void onMainActivityResult(int requestCode, int resultCode, Intent data) {}
protected void onMainPause() {}
protected void onMainResume() {}
protected void onMainDestroy() {}
protected void onGLDrawFrame(GL10 gl) {}
// singletons will always miss first onGLSurfaceChanged call
protected void onGLSurfaceChanged(GL10 gl, int width, int height) {}
}
从实例代码可以看出,真正必要的模块方法就两个 initialize
和 构造函数
,可以说是相当的简单了。
二、实现
模块实现上和其他安卓开发一样,这里就不多说了。这里说一下模块与 Godot 对象如何交互。
- 通过在模块中导出方法,上边介绍过了。使用
registerClass
注册模块中导出的方法,方法可传递简单的Java类型做为参数。 - 模块可以使用
GodotLib.calldeferred()
方法调用 Godot 对象的函数。
/*
* 调用 Godot 实例的指定函数
* @param int Godot 实例ID
* @param String 调用的 Godot 实例函数名称
* @param Object[] 传入参数
*/
GodotLib.calldeferred(int instance_id, String func_name, Object[] params);
- 向 Godot 对象发送信号。这是常见需求,模块监听到事件触发,该如何通知 Godot 对象呢?,答案是,还是用方法 2。
# Godot 项目中写法
# instance_id 所在 Node
# 定义信号
signal xx_event
# 封装一个触发函数
func on_xx_event(event_obj):
emit_signal("xx_event", event_obj)
# 其他 Node
// 模块中写法
// 调用 Godot 对象中的触发函数
GodotLib.calldeferred(instance_id, "on_xx_event", new Object[]{ event_obj });
...
// 定义一个模块导出函数,让 Godot 项目可以传入 Node 实例ID
void init(int instance_id) {
this.instance_id = instance_id;
}
Godot 项目调用自定义模块,见文章末尾。
三、编译
模块编译上还是有小细节需要说明一下
3.1 环境
Godot 是 C++ 语言开发的游戏引擎,在安卓下引擎会被编译成 so 库使用,所以除了 Android SDK
外,我们还得准备 Android NDK
(将 C++ 源码编译为 so 库)。
- Python 2.7+ or Python 3.5+
- SCons 编译系统
- 【仅Windows系统】PyWin32 (可选, 用于并行编译)
- Android SDK ,配置环境变量
ANDROID_NDK_ROOT
- 版本不低于 23.0.3
- Android build tools 版本不低于 19.1
- Android NDK,配置环境变量
ANDROID_NDK_HOME
- 版本不低于 r13
- Gradle(没得的话,编译时会自动下载)
- JDK,建议用 8
3.2 配置
先看看 SCons 编译配置 config.py 的定义
def can_build(plat):
return plat=="android"
def configure(env):
if env['platform'] == 'android':
# 包含了你自定义模块的目录
env.android_add_java_dir("Directory that contains MyCustomModule.java")
# 配置 Manifest,会被合并到 application 节点下,记得带上文件路径
env.android_add_to_manifest("AndroidManifestChunk.xml")
# 配置权限,记得带上文件路径
env.android_add_to_permissions("AndroidPermissionsChunk.xml")
# 依赖 jar 包时的配置
env.android_add_dependency("compile files('something_local.jar')")
# 配置 maven url
env.android_add_maven_repository("maven url")
# 从 maven repository 获取依赖
env.android_add_dependency("compile 'com.google.android.gms:play-services-ads:8'")
# 这个选项用途暂未验证,猜测是禁止自动引用模块到 Godot 项目
env.disable_module()
可以看出,安卓 Manifest XML被拆分为:manifest
、permissions
,这是由于需要将manifest
和并到 application 节点,而permissions
不需要这么做。如果你要查看合并后的 AndroidManifest.xml
,请查看 Godot源码目录\platform\android\java\AndroidManifest.xml
文件。
由于不需要编译 C++ 代码,所以 SCsub 文件只需要写一句
Import('env')
整个模块目录结构示例
此结构源于 github 上的开源项目,地址 gmsg
3.3 指令
实际编译指令就两条,在 Godot 引擎代码目录运行控制台程序
# C:\godot 是 Godot引擎代码所在目录
C:\godot> scons platform=android target=release_debug
C:\godot> cd platform/android/java
C:\godot\platform\android\java> gradlew build
编译指令1,scons platform=android target=release_debug
- 指令用于将引擎编译
libgodot_android.so
- target参数可以是:
debug
、release
、release_debug
- 当你修改了 Android Manifest 的XML配置文件时,需要使用该指令重新编译
编译指令2,gradlew build
- 指令用于模块代码编译
- 没其他要说的,按照编译提示排除问题就行
四、使用
4.1 引入自定义模块
这里有点小麻烦,引用模块选项没有做到 Godot 编辑器中,需要手动配置到工程文件中。
# 0. 请先关闭 Godot 编辑器
# 1. 使用你喜欢的文本编辑工具,打开项目中的 project.godot 文件
# 2. 在末尾增加如下配置要引用模块的名字
[android]
modules="org/godotengine/godot/MyCustomModule"
# 引用多个模块时,用逗号分割
# modules="org/godotengine/godot/MyCustomModule1,org/godotengine/godot/MyCustomModule2"
使用 Godot 编辑器,打开调用自定义模块的项目。
注意:如果你修改 project.godot 文件时,Godot 编辑器处于运行状态,请完全退出 Godot 编辑器进程,然后重新打开编辑器,载入项目,否则引用模块的配置不会生效。
验证配置是否成功,可以通过在编辑器中打开 项目 => 项目配置 => 一般,将左侧栏滚动条拉到底部,查看是否存在 【android】条目,点击该条目,右边就能看到我们配置的值,这说明配置已经被编辑器载入成功。
4.2 导出配置
在 Android 导出配置中,需要配置包含我们自定义模块的 APK 文件,文件会在我们编译完自定义模块后生成,位置在 Godot引擎源码\bin\android_(debug/release).apk
4.3 调用代码
最后,我们终于可以通过代码调用它了
extends Node
func _init():
if Engine.has_singleton("MyCustomModule"):
my_module = Engine.get_singleton("MyCustomModule")
my_module.init(self.get_instance_id())
# my_module.login()