☰
Godot 4 移动端开发实战:从多点触控、传感器到 Google Play 内购(mobile 目录 Demo 全解析)
2026/10/3 8:12:38 网站建设 项目流程
  • 示例工程

【免费下载链接】godot-demo-projects

Demonstration and Template Projects

项目地址:https://gitcode.com/GitHub_Trending/go/godot-demo-projects
点击查看免费下载

本篇文章以 mobile/README.md 为骨架,深入剖析 godot-demo-projects 仓库中mobile目录下的四个移动端专属 Demo:Google Play 内购(Android IAP)、多点触控方块、多点触控调试器与移动传感器。这些 Demo 依赖手机和平板才具备的硬件能力(触摸屏、传感器、应用内支付),全部使用 GDScript 编写,是学习 Godot 移动端输入、传感器融合与计费接入的实战样例。读完本文,你将掌握 Godot 移动端工程的渲染器与配置选择、多点触控手势识别、触摸状态跟踪、传感器数据解算设备朝向,以及 Google Play Billing 的完整接入流程。

移动端 Demo 一览:依赖手机特性的四个工程

mobile目录下的四个 Demo 都是独立的 Godot 工程(各自包含project.godot),它们共有的特点是:依赖手机或平板独有的功能特性,其中 Android IAP 只能运行在 Android 设备上(其余三个也需要触摸屏或传感器,在桌面端无法完整体验)。

各工程的关键信息如下表所示:

Demo 目录核心主题依赖硬件语言渲染器
mobile/android_iapGoogle Play 应用内购(Billing)Android 设备GDScriptCompatibility
mobile/multitouch_cubes多点触控输入与手势识别触摸屏(手机/平板)GDScriptCompatibility
mobile/multitouch_view多点触控调试器(实时显示触点)触摸屏GDScriptCompatibility
mobile/sensors加速度计、陀螺仪、磁力计移动传感器GDScriptMobile

值得注意的一个细节:只有sensors工程使用Mobile渲染器,其余三个均使用Compatibility渲染器。从 mobile/sensors/project.godot 中可以看到,其渲染配置为:

[rendering] renderer/rendering_method="gl_compatibility" renderer/rendering_method.mobile="gl_compatibility"

而 mobile/android_iap/project.godot、mobile/multitouch_cubes/project.godot 与 mobile/multitouch_view/project.godot 也都显式声明了renderer/rendering_method.mobile="gl_compatibility"。这说明仓库作者刻意保持了移动端工程的渲染一致性(Compatibility 即 OpenGL),以便在各类移动 GPU 上获得更广泛的兼容性。此外,这几个工程都开启了textures/vram_compression/import_etc2_astc=true,即允许纹理导入时使用 ETC2/ASTC 移动端压缩格式,可显著降低显存占用。

运行方式:如何在 Godot 中导入并启动这些 Demo

按照仓库根目录 README.md 的说明,可以一次性导入所有 Demo:

  1. 克隆本仓库(git clone https://gitcode.com/GitHub_Trending/go/godot-demo-projects)或下载 ZIP 并解压;
  2. 打开 Godot 项目管理器,点击右侧Scan(扫描)按钮;
  3. 选择包含所有 Demo 的目录;
  4. 全部 Demo 即会出现在项目管理器中,双击mobile下的任一工程即可打开运行。

也可以单独下载各个 Demo:android_iap、multitouch_cubes、multitouch_view、sensors均发布在 Godot Asset Store(由 godot-foundation 提供)。需要注意:浏览器运行无法真实体验移动端硬件特性,最好在手机/平板上用原生版本运行。多点触控类 Demo 在桌面调试时,可以通过project.godot中的pointing/emulate_touch_from_mouse=true用鼠标模拟触摸输入。

Android 应用内购 Demo:Godot × Google Play Billing 完整接入

工程目标与前置要求

mobile/android_iap/README.md 明确说明这是一个展示如何在 Godot 中使用Google Play Billing的示例工程,借助 Godot Google Play Billing 插件实现:初始化计费客户端、查询可用的应用内商品、发起购买流程、处理购买状态更新、正确确认(acknowledge)与消耗(consume)购买。

运行该 Demo 需要满足以下前置条件(均来自官方 README):

  • Godot Enginev4.2+;
  • 完成 Android Gradle 构建配置(参照官方 gradle build 文档);
  • 一个 Google Play Console 账号;
  • 在 Play Console 中创建的应用(草稿应用即可);
  • 至少配置好一个应用内商品(in-app product)。

运行步骤

  1. 在 Godot 中打开工程;
  2. 配置 Android 导出预设,包名必须与 Play Console 中的应用一致;
  3. 确认插件已正确安装到工程中(project.godot 的[editor_plugins]中声明了res://addons/GodotGooglePlayBilling/plugin.cfg);
  4. 构建并安装应用;
  5. 将应用上传到 Play Console(Internal Testing 内部测试即可)。

两条重要的注意事项:计费只对通过 Google Play 安装的应用生效;手动安装的 Debug APK 只有在设备上的 Google Play 账号被添加为license tester(许可测试员)时才可正常购买。

源码级解读:BillingClient 的完整生命周期

核心逻辑集中在 mobile/android_iap/store.gd,它继承自SplitContainer,完整演示了计费客户端的生命周期:

1. 初始化与信号连接(_init()):

billing_client = BillingClient.new() billing_client.connected.connect(_on_connected) billing_client.connect_error.connect(_on_connect_error) billing_client.query_product_details_response.connect(_on_query_product_details) billing_client.query_purchases_response.connect(_on_query_purchases) billing_client.on_purchase_updated.connect(_on_purchase_updated) billing_client.start_connection()

2. 连接成功后查询已购商品与商品详情(_on_connected()):先调用query_purchases(BillingClient.ProductType.INAPP)恢复本地已购买状态,再通过query_product_details(inapp_products.keys(), BillingClient.ProductType.INAPP)拉取商品价格等信息。这里用到了@export var inapp_products: Dictionary[String, Texture],将商品 ID 映射到图标纹理,在编辑器里即可配置。

3. 发起购买(_on_item_buy_pressed()):调用billing_client.purchase(product_id),通过返回结果的response_code与BillingClient.BillingResponseCode.OK比较来判断是否成功。

4. 处理购买更新(_on_purchase_updated()与_process_purchase()):遍历result.purchases,对每个未确认的购买调用billing_client.acknowledge_purchase(purchase.purchase_token)并等待acknowledge_purchase_response;确认成功后把product_id -> purchase_token存入owned_products字典,并将商店列表中的对应商品卡片移除。

5. 消耗购买(_on_item_consume_pressed()):通过billing_client.consume_purchase(token)消耗可消耗商品,成功后从owned_products中移除并刷新"已购物品"标签页。

6. 退出清理:_notification()中监听NOTIFICATION_WM_GO_BACK_REQUEST(Android 返回键)以及退出按钮回调,均调用billing_client.end_connection()优雅断开计费连接。

商品卡片本身封装在 mobile/android_iap/item.gd(继承PanelContainer):暴露buy_pressed/consume_pressed两个信号,通过configure()设置商品名、价格、图标;未拥有时显示"购买"按钮,已拥有时隐藏购买按钮并显示"消耗"按钮。价格文本的解析在store.gd的_get_price_string()中,从one_time_purchase_offer_details_list提取formatted_price(代码注释提示目前尚未支持订阅 offer)。

工程配置要点

mobile/android_iap/project.godot 中有几处针对移动端的配置值得借鉴:

  • window/size/viewport_width=720、viewport_height=1280的竖屏视口,配合window/handheld/orientation=1(锁定竖屏)与window/stretch/mode="canvas_items"、stretch/aspect="expand"保证不同屏幕比例下 UI 自适应;
  • theme/default_theme_scale=1.5,针对手机的高像素密度放大默认主题字号;
  • 主场景通过uid://depkfknb3soa7引用,其余资源也大量使用 UID 引用(Godot 4.4+ 的通用资源标识符机制)。

工程还提供了一个setup_instructions.tscn作为引导页(mobile/android_iap/setup_instructions.gd),点击"继续"按钮后通过get_tree().change_scene_to_file("res://store.tscn")切换到商店场景。

多点触控方块 Demo:单指旋转 + 双指缩放手势识别

mobile/multitouch_cubes/README.md 说明该 Demo 用于展示touch API 的多点触控输入与不同手势,需配合手机或平板使用。核心实现是 mobile/multitouch_cubes/gesture_area.gd,一个继承自Control的手势识别区域,通过@export var target: NodePath指定被操控的 3D 节点。

它通过导出变量开放了全部手势开关与参数,便于复用:

@export var target: NodePath @export var min_scale := 0.1 @export var max_scale := 3.0 @export var one_finger_rot_x: bool = true @export var one_finger_rot_y: bool = true @export var two_fingers_rot_z: bool = true @export var two_fingers_zoom: bool = true

手势状态机:按手指数量分派逻辑

_gui_input()以当前按下的手指数量(base_state.size())为核心做状态分派:

  • 0 根手指:接受InputEventScreenTouch.pressed,记录首个触点{index: position}到base_state;
  • 1 根手指:处理旋转(X/Y 轴)——拖拽事件中把像素位移经_px2unit()归一化为单位量(以屏幕较短边为 1),通过target_node.global_rotate(Vector3.UP, ...)和global_rotate(Vector3.RIGHT, ...)旋转目标;由于绕两轴旋转,代码会不断重置base_state与base_xform以避免累计误差;
  • 2 根手指:处理捏合缩放与绕 Z 轴旋转——计算两根手指当前向量与基准向量的长度比得到缩放系数,用clampf(base_scale * ratio, min_scale, max_scale)限制缩放范围,再通过new_segment.angle_to(base_segment)得到旋转角并global_rotate(Vector3.BACK, rot)。

_px2unit()的实现也很精练:var shortest := minf(get_size().x, get_size().y); return v * (1.0 / shortest),把像素矢量换算成以短边为基准的单位矢量,保证不同分辨率设备上手势灵敏度一致。

project.godot中pointing/emulate_touch_from_mouse=true允许在桌面端用鼠标模拟触摸来调试手势逻辑。

多点触控调试器 Demo:用单例跟踪每一个触点

mobile/multitouch_view/README.md 将其定位为多点触控输入的简易调试器:你在哪里按下,哪里就出现彩色圆点。整个工程只有两个脚本,却清晰示范了"触摸状态跟踪"与"可视化绘制"两个层次。

TouchHelper 单例:维护指针状态字典

mobile/multitouch_view/touch_helper.gd 继承自Node,通过_unhandled_input()监听未被其他节点处理的输入事件:

  • InputEventScreenTouch:按下时state[input_event.index] = input_event.position,抬起时state.erase(input_event.index);
  • InputEventScreenDrag:更新对应触点的新位置。

其公开属性state: Dictionary[int, Vector2]以指针索引为键、位置为值。脚本注释还解释了设计动机:监听未被其他方式处理的输入,并将操作系统传入的指针索引重映射为最低可用序号,使调试信息更友好。在 mobile/multitouch_view/project.godot 中它被注册为全局单例:

[autoload] TouchHelper="*res://touch_helper.gd"

这样任何场景都可以通过$"/root/TouchHelper"访问触点状态。

main.gd:每帧重绘彩色圆点

mobile/multitouch_view/main.gd 继承Node2D,在_process()中持续queue_redraw(),在_draw()中遍历touch_helper.state.keys(),为每个指针绘制一个半径 40 像素、透明度 0.75 的圆。颜色由_get_color_for_ptr_index()根据指针索引生成:

func _get_color_for_ptr_index(index: int) -> Color: var x := (index % 7) + 1 return Color(float(bool(x & 1)), float(bool(x & 2)), float(bool(x & 4)))

用索引的低 3 位比特构造 RGB 三色通道,实现"每个触点都有独特颜色"的调试效果,代码量极小且直观。

移动传感器 Demo:用加速度计、陀螺仪与磁力计解算设备朝向

mobile/sensors/README.md 说明该 Demo 展示加速度计、陀螺仪、磁力计三种常见移动传感器的用法——这些传感器通常只存在于移动设备上,桌面端无法工作。整个实现集中在 mobile/sensors/main.gd,虽然展示的是 3D 场景,但注释明确指出"读取设备朝向在 2D 游戏中同样极具价值"。

读取原始数据与兜底策略

在_process()中通过Input单例一次性读取四路传感器数据:

var acc := Input.get_accelerometer() var grav := Input.get_gravity() var mag := Input.get_magnetometer() var gyro := Input.get_gyroscope()

随后将数值格式化(%.05f)填充到 UI 标签。脚本同时给出了传感器缺失时的兜底策略:

  • 若重力向量长度小于 0.1 且加速度也接近零,则假设grav = Vector3(0.0, -1.0, 0.0)(设备水平朝上);
  • 若只有重力缺失,则用加速度计代替重力向量(因为系统通常由多传感器融合计算重力向量);
  • 若磁力计缺失,则假定磁北方向为Vector3(1.0, 0.0, 0.0)。

代码注释还提醒:这些算法均未做滤波,滤波会引入延迟但带来稳定性,实战中可参考社区实现自行补充。

核心算法:四个纯函数解算朝向

main.gd提供了四个可直接复用的矢量/矩阵算法:

  1. get_basis_for_arrow(p_vector):由方向向量构造旋转矩阵,用于把箭头模型指向指定方向。先让rotate.y = p_vector.normalized(),再用叉积依次构造互相垂直的x、z轴;为规避万向锁,当初始辅助向量与目标方向点积绝对值大于 0.9 时切换辅助向量。

  2. calc_north(p_grav, p_mag):用重力向量与磁力计读数计算指向"地平线对齐的北方"的向量——先叉积得到东西向,再与重力叉积得到北方。注释风趣地提醒:必须始终使用归一化向量。

  3. orientate_by_mag_and_grav(p_mag, p_grav):结合磁力计与重力构造朝向矩阵(rotate.y = -p_grav.normalized(),重力向下故取反为"上"),该方法不依赖陀螺仪,适合没有陀螺仪的低端机型,但易受磁体干扰。

  4. rotate_by_gyro(p_gyro, p_basis, p_delta):陀螺仪输出的是角速度而非方向,因此需要乘以delta积分:

rotate = rotate.rotated(p_basis.x, -p_gyro.x * p_delta) rotate = rotate.rotated(p_basis.y, -p_gyro.y * p_delta) rotate = rotate.rotated(p_basis.z, -p_gyro.z * p_delta) return rotate * p_basis
  1. drift_correction(p_basis, p_grav):陀螺仪积分会产生漂移,该函数用重力向量做纠偏——点积得到夹角余弦,叉积得到旋转轴,构造旋转矩阵修正基向量,当dot < 1.0时执行修正。

在_process()末尾,Demo 用两套方案分别驱动两个方块:orientate_by_mag_and_grav()组合磁力计+重力(抗干扰差但可用),以及rotate_by_gyro()+drift_correction()组合陀螺仪+重力(效果最佳)。

工程配置差异:唯一使用 Mobile 渲染器的工程

mobile/sensors/project.godot 中renderer/rendering_method.mobile="gl_compatibility"与其他工程一致,但根 README 明确指出该工程在概念上对应Mobile 渲染器分类;同时开启了anti_aliasing/quality/msaa_3d=2(2x MSAA 抗锯齿)以改善 3D 场景锯齿,并启用 ETC2/ASTC 纹理压缩。此外window/stretch/mode="canvas_items"保证 UI 按画布尺寸缩放,适配不同分辨率的手机屏幕。

小结:移动端开发的通用模式与复用建议

综合mobile目录四个 Demo,可以总结出几条可复用的 Godot 移动端开发模式:

  • 触摸输入:优先在_unhandled_input()或_gui_input()中处理InputEventScreenTouch/InputEventScreenDrag,用字典按index跟踪触点,并按手指数量分派手势逻辑(参考 gesture_area.gd);
  • 调试手段:把触摸状态做成 Autoload 单例(参考 touch_helper.gd),配合Node2D._draw()可视化,是排查多点触控问题的高效手段;
  • 传感器使用:通过Input.get_accelerometer()等 API 读取原始数据,用重力向量纠偏陀螺仪漂移、用磁力计补足无陀螺仪设备(参考 main.gd);
  • 移动配置:所有工程均统一使用 Compatibility 渲染器、开启 ETC2/ASTC 纹理压缩,并通过emulate_touch_from_mouse支持桌面调试;
  • 应用内购:遵循"连接 → 查询 → 购买 → 确认/消耗"的完整计费生命周期,并对购买结果逐项校验response_code(参考 store.gd)。

这些 Demo 均可直接作为移动端项目的起点模板:把gesture_area.gd复制到需要手势控制的 3D 场景,把TouchHelper单例引入需要调试触摸的游戏,把传感器算法函数移植到体感或 AR 类玩法,把store.gd的计费流程套用到自己的商店系统。每个工程都包含project.godot,可以直接在 Godot 项目管理器中打开运行、按需裁剪。

  • 示例工程

【免费下载链接】godot-demo-projects

Demonstration and Template Projects

项目地址:https://gitcode.com/GitHub_Trending/go/godot-demo-projects
点击查看免费下载

相关推荐

上一篇:Prototool 使用指南
下一篇:F´ Fw::Types 类型系统详解:从基础类型别名到 PolyType 多态类型容器

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询