godot 3.0 开发自定义android模块

你这是要为难我 Godot ?

相关的官方文档有两篇:

  • 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 对象如何交互。

  1. 通过在模块中导出方法,上边介绍过了。使用registerClass注册模块中导出的方法,方法可传递简单的Java类型做为参数。
  2. 模块可以使用 GodotLib.calldeferred() 方法调用 Godot 对象的函数。
/*
  * 调用 Godot 实例的指定函数
  * @param int Godot 实例ID
  * @param String 调用的 Godot 实例函数名称
  * @param Object[] 传入参数
  */
GodotLib.calldeferred(int instance_id, String func_name, Object[] params);
  1. 向 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被拆分为:manifestpermissions,这是由于需要将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参数可以是:debugreleaserelease_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】条目,点击该条目,右边就能看到我们配置的值,这说明配置已经被编辑器载入成功。


自定义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()

你可能感兴趣的:(godot 3.0 开发自定义android模块)