mcpField
G
godot-game-loop-time-trial

godot-game-loop-time-trial

github.com/thedivergentai开发907239 次安装2 周前更新
代码仓库

关于 godot-game-loop-time-trial

godot-game-loop-time-trial 是用于 Godot 竞速计时赛的技能,涵盖按序验证检查点、精确计时和视觉幽灵回放。它指导开发者构建管理器、检查点、记录、回放及排行榜组件。

主要功能

  1. 01按序验证检查点
  2. 02微秒或物理帧计时
  3. 03记录变换与 Quaternion 旋转
  4. 04插值播放幽灵轨迹
  5. 05格式化排行榜时间

适用场景

  1. 01构建基于检查点的竞速计时器
  2. 02录制并回放幽灵路线
  3. 03保存最佳时间和幽灵数据
  4. 04为排行榜格式化圈速记录

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/thedivergentai/game-dev-agentic-skills --skill godot-game-loop-time-trial

安装后在 Claude Code 中输入/godot-game-loop-time-trial确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

references/
migration-notes.md
time-trial-expert-patterns.md
scripts/
ghost_recorder.gd
ghost_replayer.gd
time_trial_leaderboard_bridge.gd
time_trial_manager.gd
time_trial_patterns.gd
time_trial_playback_buffer.gd

详细介绍

架构设计: “验证链”模式

Master 实现将计时赛视为一个经过状态验证的序列。记录时间很容易;要确保玩家没有通过走捷径作弊,则需要一个严格有序的 CheckpointManager。

核心职责
  • TimeTrialManager:中央计时器。验证检查点顺序并处理“最佳圈速”逻辑。
  • GhostRecorder:采集高频变换数据。使用增量时间戳,实现与帧率无关的回放。
  • Checkpoint:空间触发器,用于通知 Manager。

专家级代码模式

1. 稳健的检查点验证

要求按数字顺序通过检查点,防止“走捷径作弊”。

将 Area 的 body_entered(物理)连接到 → TimeTrialManager.pass_checkpoint(index)。计时器由 Manager 管理(单位为 usec)——请参阅脚本。

2. 节省空间的 Ghost 记录

以固定频率采样(例如 10 Hz)。对位置进行 Lerp;对旋转使用 slerp Quaternion(ghost_recorder.gd / ghost_replayer.gd)。绝不要对 Ghost 朝向进行欧拉角 Lerp。

Master 决策矩阵:数据存储

格式最适合实现方式
Dictionary Array原型设计简单的 [{t: 0.1, p: pos}, ...]
Typed Array性能使用 PackedVector3Array 存储位置。
JSON/Binary保存使用 FileAccess.get_var() 保存 Ghost 文件。

绝对不要做

  • 绝对不要使用 OS.get_ticks_msec() 进行超高精度的竞速计时 — 毫秒级精度对于高端竞速游戏来说太粗糙。请使用 Time.get_ticks_usec(),以获得微秒级精度。
  • 绝对不要只依赖 _process() 触发终点线检测 — 延迟期间可能会跳过画面帧。务必在 _physics_process() 中检测物理重叠,确保在固定物理步长内完成检测。
  • 绝对不要在实例化后立即检测 Area3D 重叠 — 物理服务器至少需要一个物理帧来完成同步。在检查玩家之前,先执行 await get_tree().physics_frame。
  • 绝对不要对检查点上的 CollisionShape3D 使用非等比缩放 — 这会破坏底层的 SAT 碰撞计算。应始终缩放内部形状资源(例如 BoxShape3D.size)。
  • 绝对不要在多人竞速中使用 TCP(可靠传输)同步位置 — 拥塞算法会造成巨大的延迟峰值。对于高频位置更新,请使用 ENetMultiplayerPeer 和 TRANSFER_MODE_UNRELIABLE。
  • 绝对不要信任客户端对终点线或圈数的判定 — 务必在权威服务器上使用 multiplayer.is_server() 验证触发事件,以防作弊。
  • 绝对不要使用标准浮点数相等比较(==)来比较纪录圈速 — 使用 is_equal_approx(),以应对累积时间变量中的精度损失。
  • 绝对不要在不清空缓冲区的情况下硬编码输入检测 — 为了实现帧级精准的加速/停止响应,请调用 Input.flush_buffered_events(),确保引擎已处理最新的原始输入。
  • 绝对不要在快速路径跟随循环中分配新的 Vector3 数组 — 这会触发垃圾回收。请使用 PackedVector3Array 来维持连续内存块。
  • 绝对不要在紧密循环中使用动态字符串路径($"../Checkpoint") — 查找速度很慢。请使用 @onready 在初始化期间缓存节点引用。
  • 绝对不要为幽灵记录整个玩家对象 — 只记录核心变换(位置/旋转)。记录整个对象会消耗大量内存,而且对于视觉幽灵来说没有必要。
  • 绝对不要给幽灵添加碰撞 — 幽灵应该只是视觉指示器(例如半透明),以免干扰玩家的行驶路线。
  • 绝对不要忽略检查点顺序 — 不要只检查玩家是否到达终点线。请确认玩家按正确顺序通过了所有中间检查点。
  • 绝对不要在未优化监测的情况下使用 Area3D — 检查点只应检测 Player 物理层,以尽量减少物理重叠计算次数。
  • 绝对不要对幽灵旋转使用标准 lerp — 使用 slerp() 或 Quaternion.slerp(),以避免万向节锁并确保旋转插值平滑。

可用脚本

必须遵循:按照黄金路径顺序操作。在为对应阶段编写代码前,先阅读其中列出的脚本。

黄金路径(必须遵循)
  1. time_trial_manager.gd — 使用微秒(Time.get_ticks_usec)或物理帧计时;只能通过物理重叠/Area 信号调用 pass_checkpoint
  2. 检查点 Area — 使用有序索引指向管理器(基于物理帧,而非 _process)
  3. ghost_recorder.gd — 采样 {t, p, q},其中旋转使用 Quaternion
  4. ghost_replayer.gd — 位置使用 lerp,Quaternion 使用 slerp(绝不使用 Euler lerp)
  5. time_trial_leaderboard_bridge.gd — 将整数微秒/毫秒转换为 UI 字符串
脚本索引
time_trial_patterns.gd

10 种专家模式:微秒计时、服务器权威验证、橡皮筋 AI,以及帧级精准的输入缓冲区清空。

time_trial_manager.gd

中央时钟。累积 Time.get_ticks_usec()(或物理帧计数)。终点检查必须通过物理重叠触发。

ghost_recorder.gd

捕获包含 Quaternion "q" 字段的变换样本,以便安全地使用 slerp 播放。

ghost_replayer.gd

与录制器配套的必备脚本。通过位置 lerp + Quaternion.slerp 重放样本。

time_trial_playback_buffer.gd

用于网络流传输期间流畅回放幽灵数据的抖动缓冲区。

time_trial_leaderboard_bridge.gd

用于将原始时间数据转换为易读字符串的格式化工具。


专家级计时赛模式

1. 幽灵数据的增量压缩

仅当位置/旋转变化超过阈值时才存储关键帧。使用 FileAccess.open_compressed() + ZSTD 持久化;优先使用二进制浮点数,而非 JSON。

2. 排行榜桥接工具

以 int 微秒/毫秒存储记录。使用 %02d:%02d.%03d 格式化,确保 UI 稳定显示(例如 01:24.450)。

专家知识(按需获取)

**大模型无知规则:**如果通用 Agent 在阅读前不会了解某项内容,就加载参考资料 — 永远不要删除专家增量内容。

参考资料

渐进式披露:仅在研究特定 API 时打开官方文档链接;在切换到相邻领域时加载相关技能 — 不要预加载整个知识网络。

官方文档
  • 时间 — 当 OS.get_ticks_msec() 对比赛记录而言精度不足时,使用 get_ticks_usec() 获取微秒级单圈计时。
  • 空闲与物理处理 — 说明终点线和检查点的重叠检测为何必须在 _physics_process 中运行,而不能依赖负载较高时可能跳过的视觉 _process 帧。
  • Area3D — 通过监控、碰撞层和 body_entered,按顺序设置检查点门,无需扫描每个物理物体。
  • 碰撞形状(3D) — 调整形状资源(BoxShape3D.size)的大小,而不是对 CollisionShape3D 使用非均匀缩放,以确保门上的 SAT 有效。
  • 使用变换 — 说明如何为幽灵样本捕获全局位置/基底,以及为何仅存储欧拉角时需要谨慎进行回放转换。
  • Quaternion — 在关键帧之间使用 slerp(),避免幽灵朝向在朴素欧拉角线性插值时出现万向节锁。
  • Transform3D — 使用 interpolate_with() 在有序帧之间回放抖动缓冲的网络幽灵数据。
  • 保存游戏 — 使用 FileAccess / store_var 模式持久化幽灵跑圈数据和最佳时间字典,避免浮点数显示往返转换。
  • 高级多人游戏 — 使用服务器权威 RPC 验证,防止客户端伪造单圈/终点线穿越。
  • MultiplayerPeer — 对高频赛车变换使用 TRANSFER_MODE_UNRELIABLE,避免类似 TCP 的可靠传输导致延迟激增。
  • 输入 — 当帧级精度的加速/停止操作必须在物理步进前读取最新原始输入时,使用 flush_buffered_events()。
  • Engine — 使用 physics_ticks_per_second / get_physics_frames() 将整数帧计时桥接到 MM:SS.mmm UI。
相关技能
前置条件
  • godot-project-foundations — 在将 TimeTrialManager 和检查点区域接入赛道场景前,先了解场景树、自动加载项和资源布局。
  • godot-physics-3d — 了解 Area3D/CollisionShape3D 层、RigidBody/CharacterBody 载具,以及确保检查点顺序可靠的物理帧重叠规则。
  • godot-signal-architecture — 在闸门、管理器、HUD 和幽灵系统之间传递类型化的单圈/分段/完赛信号,避免脆弱的节点路径耦合。
  • godot-gdscript-mastery — 掌握计时和权限模式中用到的类型化数组、Packed* 缓冲区、await physics_frame 和 RPC 注解。
补充
  • godot-input-handling — 时间挑战 NEVER 规则要求在物理帧前清空的动作映射和缓冲加速/转向输入。
  • godot-save-load-systems — 超越内存样本数组,了解压缩二进制幽灵文件和最佳成绩持久化。
  • godot-multiplayer-networking — 用于实时比赛和流式传输幽灵帧的 ENet 对等节点、权限和不可靠变换同步。
  • godot-adapt-single-to-multiplayer — 将单人时间挑战扩展为在线竞速时所需的延迟补偿、快照和兴趣管理模式。
  • godot-navigation-pathfinding — 使用 NavigationServer3D Agent 的最高速度设置橡皮筋 AI,使其与玩家保持节奏,同时不通过碰撞作弊。
  • godot-monte-carlo-balancer — 在发布挑战参数前,模拟橡皮筋系数、检查点难度和目标通关时间。
  • godot-camera-systems — 追逐/回放摄像机必须在播放期间跟踪实时赛车和无碰撞的幽灵视觉效果。
下游 / 使用方
  • godot-genre-racing — 完整的竞速游戏类型技术栈,将检查点计时、幽灵和排行榜格式作为核心循环基础机制。
  • godot-game-loop-collection — 元游戏库存/收集循环,可依据此技能验证过的最佳成绩来设置解锁条件。
主模块
  • godot-master — 用于跨技能发现的库路由器和镜像模块入口。

评论

支持 Markdown