scenario-godot-gameplay
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseGodot gameplay systems (gameplay systems programmer)
Godot gameplay systems(gameplay systems 程序员)
Target: Godot 4.7.2.stable, Jolt, macOS Apple Silicon.
At expert level, gameplay systems are small contracts that can be tested without a scene: pure decision functions, Resources for data, groups for discovery. Their cost is measured at the agent count the game needs before anyone argues about it. The core stance: build the rule as data, run it headless at , then look at one capture. If a sibling skill named here is missing from your available skills, ask the user to install it (); unattended, proceed from tool schemas and flag the gap.
--fixed-fps 60npx skills add scenario-labs/skills --skill <name>REQUIRED BACKGROUND: scenario-godot-expert (channels, , the review loop, 4.7 traps).
gd_runStatus (2026-10-02): 16 live tests, the round-2 checks (P15) and the offline suite pass in Godot 4.7.2 (, ). Dialogue Manager 4.1.0, LimboAI 1.8.1 and GUT 9.7.1 were run in their own project copies.
references/procedures.mdtests/code/godot-gameplay/目标:Godot 4.7.2.stable,Jolt,macOS Apple Silicon。
在专家水平上,gameplay systems 是一组无需场景即可测试的小型契约:纯决策函数、用于存储数据的 Resources,以及用于发现的 groups。其成本衡量标准是游戏所需的智能体数量,在此之前不会有人争论性能。核心原则是:将规则构建为数据,以 在 headless 环境中运行,然后查看一次 capture。如果这里提到的某个同级 skill 在可用 skills 中缺失,请要求用户安装();在无人值守的情况下,则根据 tool schemas 继续操作并标记该缺口。
--fixed-fps 60npx skills add scenario-labs/skills --skill <name>必需背景: scenario-godot-expert(channels、、review loop、4.7 traps)。
gd_run状态(2026-10-02): 16 项 live tests 已通过;第二轮检查(P15)和 offline suite 在 Godot 4.7.2 中通过(、)。Dialogue Manager 4.1.0、LimboAI 1.8.1 和 GUT 9.7.1 均在各自的项目副本中运行。
references/procedures.mdtests/code/godot-gameplay/Stance (the expert delta)
专家视角的关键差异
- Benchmark with , never plain headless. A headless frame sleeps 6.9 ms (
--fixed-fps 60) and runs fewer physics ticks than frames.low_processor_usage_mode_sleep_usecmonitors refresh about once per second and read 0 under fixed fps. Measure wall milliseconds per frame, median of 3, and compare A/B pairs from the same run (observed, P0).Performance.TIME_* - The crowd is not the bottleneck the baseline thinks. 200 CharacterBody3D enemies with NavigationAgent3D avoidance cost about 2 ms per frame on an M5 Max. Cost is linear to 800 agents (7.3 ms), and avoidance itself is within noise at 200. Tuning or the repath interval gave no measurable gain. What avoidance buys is correctness: 0 overlapping pairs against 3108 without it (P2). Go to server agents plus one MultiMesh (0.26 ms for 200) only when the agents need no nodes.
max_neighbors - Wait for the mesh you assigned, not for "the map". The docs say wait one physics frame. Live, the first sync took 3. After a rebake the map id moved while the region still served the old polygons. Read before assigning, wait for it to move, then one more map sync (
region_get_iteration_id, P1).nav_tools.wait_applied - Bake from a group of static colliders. A new NavigationMesh parses Both (meshes and colliders) from the region's children, so an NPC under the region carves a 3 m hole (Bramwell 2W4JP48oZ8U 00:12:37; measured P1).
- Pick the AI tier by the deciding condition. Use an enum brain for crowds (Shaggy Dev oqFbZoA2lnU 00:00:32) and a node FSM for a hero or player character. Use a behavior tree when designers author behavior (Chap.C E_FIy2dTkNc), and GOAP only when many generic actions recombine (Wahaha Yes cm5Jxo31plw). Budget thinking: 5 Hz with 40 enemies per tick cost 0.07 ms over no AI; every enemy every tick cost 0.45 ms (P3).
- Hitboxes mask, hurtboxes layer, one HitLog per swing (Queble cX-vzfmzjnE 00:06:36, 00:12:55). New areas start on layer 1 and mask 1 and hit their own owner (P4).
- Fast bullets are data, or bodies with CCD. Without , 6 of 8 balls went through a 0.1 m wall even at 30 m/s. Jolt clamps at 500 m/s. Ray-swept data bullets drawn by one MultiMesh cost 0.35 ms per 1000, against 1.05 ms for pooled RigidBody3D with CCD (P5).
continuous_cd - A save is code. A GDScript sub_resource runs on load (Godotneers 43BZsLZheA4 01:03:14; reproduced P6). Scan before loading, load with
.tres, version and migrate, validate values instead of encrypting (01:01:37).CACHE_MODE_IGNORE
- 使用 进行基准测试,绝不要使用普通 headless。 headless frame 会休眠 6.9 ms(
--fixed-fps 60),其 physics tick 数量少于 frame 数量。low_processor_usage_mode_sleep_usecmonitors 约每秒刷新一次,在 fixed fps 下读取结果为 0。测量每帧的 wall milliseconds,取 3 次结果的中位数,并比较同一次运行中的 A/B 对(实测值,P0)。Performance.TIME_* - 人群并不是 baseline 所认为的瓶颈。 在 M5 Max 上,200 个使用 NavigationAgent3D avoidance 的 CharacterBody3D 敌人每帧约耗费 2 ms。成本随智能体数量线性增长到 800 个(7.3 ms),而在 200 个时,avoidance 本身仍处于噪声范围内。调整 或 repath interval 没有带来可测量的收益。avoidance 带来的价值是正确性:不开启时检测到 3108 对重叠,而开启后为 0(P2)。只有在智能体不需要节点时,才改用 server agents 加一个 MultiMesh(200 个为 0.26 ms)。
max_neighbors - 等待你分配的 mesh,而不是等待“the map”。 文档要求等待一个 physics frame。实际运行时,第一次同步用了 3 个 frame。重新 bake 后,map id 发生了变化,而 region 仍在提供旧 polygons。先读取 再进行分配,等待其发生变化,然后再执行一次 map sync(
region_get_iteration_id,P1)。nav_tools.wait_applied - 从一组 static colliders 执行 bake。 新建的 NavigationMesh 会从 region 的 children 中解析 Both(meshes 和 colliders),因此位于 region 下的 NPC 会在地图上挖出一个 3 m 的孔洞(Bramwell 2W4JP48oZ8U 00:12:37;实测值 P1)。
- 根据决定性条件选择 AI 层级。 人群使用 enum brain(Shaggy Dev oqFbZoA2lnU 00:00:32),主角或玩家角色使用 node FSM。当由设计师编写行为时使用 behavior tree(Chap.C E_FIy2dTkNc),只有当大量通用 actions 需要重新组合时才使用 GOAP(Wahaha Yes cm5Jxo31plw)。思考预算方面:以 5 Hz 让 40 个敌人每个 tick 思考一次,相比无 AI 额外耗费 0.07 ms;每个敌人每个 tick 都思考则耗费 0.45 ms(P3)。
- Hitboxes 使用 mask,hurtboxes 使用 layer,每次挥击只生成一个 HitLog(Queble cX-vzfmzjnE 00:06:36、00:12:55)。新建的 Area 默认位于 layer 1 且 mask 为 1,会命中自身的 owner(P4)。
- 高速子弹要么采用数据驱动,要么使用带 CCD 的 bodies。 没有 时,即使速度为 30 m/s,8 个球体中也有 6 个穿过了 0.1 m 厚的墙。Jolt 会将速度限制在 500 m/s。由单个 MultiMesh 绘制的 ray-swept 数据子弹,每 1000 个耗费 0.35 ms;采用带 CCD 的池化 RigidBody3D 则为 1.05 ms(P5)。
continuous_cd - 存档本质上就是代码。 加载时,GDScript sub_resource 会被执行(Godotneers 43BZsLZheA4 01:03:14;已复现 P6)。加载前先进行扫描,使用
.tres加载,添加 version 并执行 migrate,验证数值,而不是加密(01:01:37)。CACHE_MODE_IGNORE
The NavigationAgent3D contract (P15, measured)
NavigationAgent3D 契约(P15,实测)
Docs warnings (NavigationAgents page) and Bramwell (2W4JP48oZ8U 00:14:14), measured in 4.7.2 unless marked:
- Avoidance needs a . With avoidance on and no target,
target_positionstayed 0 for 30 ticks; with a target it returned the full 3 m/s.safe_velocity - Avoidance never feeds pathfinding. Agents are circles with no navmesh or physics knowledge, so walls still come from the path (docs).
- One per physics frame, and none after the end. Once
get_next_path_position()is true it still returns the last point (0.93 m away here): stop steering there, or the agent creeps.is_navigation_finished() - must exceed one tick of travel and the navmesh's float above the floor (about 0.3 m). At 25 m/s (0.42 m per tick) with 0.1, the agent reversed on 1782 of 1800 ticks and never arrived; at 1.0 it arrived in 182. With 0.1 and the feet measured at floor height, it never left the first path point.
path_desired_distance - Defaults: 1.0,
time_horizon_agents0.0. Lower the horizon if agents slow down too early. Too fewtime_horizon_obstaclesand avoidance is ignored (docs; not measured here).max_neighbors
除非另有标记,以下结果均在 4.7.2 中实测:
- Avoidance 需要 。 开启 avoidance 却没有 target 时,
target_position在 30 个 tick 中始终为 0;设置 target 后,它恢复为完整的 3 m/s。safe_velocity - Avoidance 永远不会反馈给 pathfinding。 Agents 是 circles,不具备 navmesh 或 physics 知识,因此墙体仍来自 path(docs)。
- 每个 physics frame 调用一次 ,路径结束后不要再调用。 一旦
get_next_path_position()为 true,它仍会返回最后一个点(此处距离目标 0.93 m):应在此停止 steering,否则智能体会缓慢爬行。is_navigation_finished() - 必须大于一个 tick 的移动距离,并大于 navmesh 相对地面的悬浮高度(约 0.3 m)。 在 25 m/s(每 tick 0.42 m)且阈值为 0.1 时,智能体在 1800 个 tick 中的 1782 个都在反向移动,始终无法到达;阈值为 1.0 时,它在 182 个 tick 后到达。若阈值为 0.1 且脚部测得高度等于地面,它甚至无法离开第一个路径点。
path_desired_distance - 默认值: 为 1.0,
time_horizon_agents为 0.0。如果智能体过早减速,应降低 horizon。time_horizon_obstacles太少时,avoidance 会被忽略(docs;此处未实测)。max_neighbors
Establish first
首先确定
| Input | Why it changes the plan | Default |
|---|---|---|
| Agent count on screen | nodes vs server agents, think budget | 200 |
| Frame budget for gameplay | the gate for every benchmark | a quarter of 16.67 ms (4.2 ms) at 60 fps [added] |
| 2D or 3D | NavigationAgent2D vs 3D, Area2D vs 3D | 3D |
| Who authors behavior | code (FSM, enum) vs designers (LimboAI) | code |
| Save trust | own files only vs shared or modded saves | shared: scan or JSON |
| Platform | input devices, CPU budget | desktop, keyboard and mouse plus pad |
| 输入 | 为什么会改变方案 | 默认值 |
|---|---|---|
| 屏幕上的智能体数量 | 使用 nodes 还是 server agents,以及思考预算 | 200 |
| gameplay 的帧预算 | 所有基准测试的门限 | 60 fps 下 16.67 ms 的四分之一(4.2 ms)[added] |
| 2D 或 3D | NavigationAgent2D 与 3D、Area2D 与 3D | 3D |
| 谁编写行为 | code(FSM、enum)还是设计师(LimboAI) | code |
| 存档信任级别 | 仅信任自己的文件,还是信任共享或 modded 存档 | 共享:扫描或使用 JSON |
| 平台 | 输入设备、CPU 预算 | 桌面端、键盘和鼠标以及手柄 |
Workflow
工作流
- Set up the project.
- Clone Base3D with and give it its own
gd_env.base_project("3d", P), because clones otherwise shareapplication/config/name. Runuser://.gg.install(P) - GATE: project.godot has and a stated renderer;
3d/physics_engine="Jolt Physics"reports 0 parse errors.gd_run.check_all(P)
- Clone Base3D with
- Level navigation.
- Static geometry goes in group . Build the mesh with
nav_source, thenmake_navmesh(parsed colliders, source group), thenbake.wait_applied - GATE: between sample points is non-empty with 0 obstacle crossings; the polygon count is above 0; no hole at NPC spawns (P1).
map_get_path
- Static geometry goes in group
- Movement and the crowd.
- Enable avoidance; drives
velocity_computed; repath is throttled; steering is XZ only.move_and_slide - Run at 50, 200 and 800, then
gg.crowd_bench(P, n). In your own benchmark scene, loggg.scaling_verdictandPerformance.add_custom_monitor(&"ai/thinks", callable)beside wall time (it read 5 after 5 strayOBJECT_ORPHAN_NODE_COUNT, P15).Node.new() - GATE: 0 overlapping pairs; exponent under 1.3; the median at the target count fits the gameplay budget (); the orphan count is flat. Then a windowed capture of the crowd, opened.
gg.budget_share
- Enable avoidance;
- AI.
- Write the brain as with hysteresis. Perception is cheap first (distance, cone, one ray, stale-hit check). The manager thinks at about 5 Hz with a per-tick cap. Far enemies think less: key the tiers on squared distance, because
decide(state, percept)stays false headless and a benchmark would put everyone in the far tier (P15). The node FSM is for the hero; LimboAI if designers author.VisibleOnScreenNotifier3D.is_on_screen() - GATE: the GUT transition table is green; the hero scenario history matches the expected sequence (patrol, chase, attack, chase, search, patrol); the think-cost A/B is measured (P3, P9, P13).
- Write the brain as
- Combat.
- Name the layers (World 1, Player 2, Enemy 3, PlayerHurtbox 5, EnemyHurtbox 6, Projectile 7). Hitbox and hurtbox come from the kit. Bullets go through ; bouncing objects are RigidBody3D with CCD.
bullet_pool - GATE: a shared-log swing scores 1 hit; same faction 0; the tunnelling test reads 0 of 8 at the top speed; bullets on their own layer (P4, P5).
- Name the layers (World 1, Player 2, Enemy 3, PlayerHurtbox 5, EnemyHurtbox 6, Projectile 7). Hitbox and hurtbox come from the kit. Bullets go through
- Persistence.
- Typed save Resource with VERSION and ,
migrate(),save_io.save_resource_atomic; inventories duplicated per holder.load_resource_checked - GATE: round trip equal; every old fixture loads; the evil fixture is refused; the cache test passes (P6, P7).
- Typed save Resource with VERSION and
- Dialogue and quests.
- Dialogue Manager 4.x files; quest order is turn in, then continue, then offer.
.dialogue - GATE: the import compiles every file with 0 errors; finds no missing cue; a headless walk reaches each branch and mutates state (P8).
gg.check_dialogue_text
- Dialogue Manager 4.x
- Input.
- Physical-key actions; gameplay in ; remaps go to a ConfigFile.
_unhandled_input - GATE: synthetic press and just-pressed tests pass; the STOP panel consumes a pushed click; the remap survives a reload (P10).
- Physical-key actions; gameplay in
- Procedural content.
- Seeded data first (), validators, then geometry, bake and path.
dungeon_gen - GATE: 1000 seeds with 0 validator failures; the same seed gives the same hash; a path from start to boss exists; the top capture is opened (P11).
- Seeded data first (
- Wrap up.
- Run and copy the evidence. Score yourself against
test_gameplay_live.py.references/critique.md
- Run
- 设置项目。
- 使用 克隆 Base3D,并为其设置独立的
gd_env.base_project("3d", P),因为克隆项目默认共享application/config/name。运行user://。gg.install(P) - GATE:project.godot 中包含 和已声明的 renderer;
3d/physics_engine="Jolt Physics"报告 0 个解析错误。gd_run.check_all(P)
- 使用
- 关卡导航。
- 将静态几何体放入 group 。使用
nav_source构建 mesh,然后依次执行make_navmesh(parsed colliders, source group)和bake。wait_applied - GATE:采样点之间的 非空且没有穿越障碍物;polygon 数量大于 0;NPC 出生点处没有孔洞(P1)。
map_get_path
- 将静态几何体放入 group
- 移动与人群。
- 启用 avoidance;由 驱动
velocity_computed;对 repath 进行节流;steering 仅限 XZ。move_and_slide - 在 50、200 和 800 个智能体时分别运行 ,然后运行
gg.crowd_bench(P, n)。在自有 benchmark scene 中,将gg.scaling_verdict和Performance.add_custom_monitor(&"ai/thinks", callable)与 wall time 一起记录(在 5 次遗留OBJECT_ORPHAN_NODE_COUNT后该值为 5,P15)。Node.new() - GATE:重叠对数为 0;指数低于 1.3;目标数量下的中位耗时符合 gameplay 预算();orphan 数量保持稳定。然后打开人群的窗口化 capture。
gg.budget_share
- 启用 avoidance;由
- AI。
- 使用 hysteresis 编写 brain。优先采用低成本 perception(距离、cone、一条 ray、stale-hit check)。manager 以约 5 Hz 思考,并设置每个 tick 的上限。远距离敌人应减少思考:按距离平方划分 tier,因为
decide(state, percept)在 headless 环境中始终为 false,而基准测试会将所有敌人放入 far tier(P15)。node FSM 用于主角;如果由设计师编写行为,则使用 LimboAI。VisibleOnScreenNotifier3D.is_on_screen() - GATE:GUT transition table 全部通过;主角场景历史符合预期顺序(、
patrol、chase、attack、chase、search);已测量思考成本的 A/B 对比(P3、P9、P13)。patrol
- 使用 hysteresis 编写
- 战斗。
- 为 layers 命名(World 1、Player 2、Enemy 3、PlayerHurtbox 5、EnemyHurtbox 6、Projectile 7)。使用 kit 中的 hitbox 和 hurtbox。子弹通过 处理;需要反弹的 objects 使用带 CCD 的 RigidBody3D。
bullet_pool - GATE:使用 shared log 的挥击计为 1 次命中;同阵营计为 0;最高速度下的 tunnelling test 结果为 8 发中 0 发穿墙;子弹位于自己的 layer(P4、P5)。
- 为 layers 命名(World 1、Player 2、Enemy 3、PlayerHurtbox 5、EnemyHurtbox 6、Projectile 7)。使用 kit 中的 hitbox 和 hurtbox。子弹通过
- 持久化。
- 使用带 VERSION 和 的 typed save Resource,并使用
migrate()、save_io.save_resource_atomic;每个 holder 的 inventories 都要单独复制。load_resource_checked - GATE:往返结果一致;所有旧 fixtures 均可加载;恶意 fixture 被拒绝;cache test 通过(P6、P7)。
- 使用带 VERSION 和
- 对话与任务。
- 使用 Dialogue Manager 4.x 的 文件;任务顺序为先 turn in,再 continue,最后 offer。
.dialogue - GATE:import 编译所有文件且 0 个错误;未发现缺失的 cue;headless walk 到达每个 branch 并改变状态(P8)。
gg.check_dialogue_text
- 使用 Dialogue Manager 4.x 的
- 输入。
- Actions 使用 physical keys;gameplay 放在 中;remaps 写入 ConfigFile。
_unhandled_input - GATE:synthetic press 和 just-pressed tests 通过;STOP 面板会消费按下的点击事件;remap 在重新加载后仍然有效(P10)。
- Actions 使用 physical keys;gameplay 放在
- 程序化内容。
- 先生成 seeded data(),再运行 validators,之后生成 geometry、bake 和 path。
dungeon_gen - GATE:1000 个 seeds 产生 0 个 validator failures;相同 seed 产生相同 hash;从起点到 boss 的 path 存在;打开俯视 capture(P11)。
- 先生成 seeded data(
- 收尾。
- 运行 并复制证据。根据
test_gameplay_live.py对自身进行评分。references/critique.md
- 运行
Numbers
数值
| Value | Measured | Relative to |
|---|---|---|
| 200 bodies with avoidance | 1.98 ms per frame, 0 overlaps | M5 Max, fixed fps 60, 60 m arena with 14 obstacles |
| Scaling with avoidance | 50 agents: 1.07 ms, 200: 2.00, 800: 7.31 (about 9 µs per agent) | same |
| 200 server agents plus MultiMesh | 0.26 ms | same |
| Think cost, 200 enemies | budget 0.40 ms, every tick 0.78, none 0.33 | 5 Hz, 40 per tick |
| First navmesh sync | 3 physics frames; rebake applied after 2 to 16 | async iterations on (default) |
| Bake | 5 ms, 180 polygons | 60 m arena, cell 0.25 |
| 1000 bullets | data 0.35 ms; RigidBody3D with CCD 1.05; without CCD 1.00 (45% miss walls) | 60 m/s, 2 s life |
| Jolt speed clamp | 500 m/s | |
| Dungeon generate plus validate | 88 µs median, 1000 of 1000 valid | 14-room main path, 4 branches |
| NavigationAgent3D defaults | radius 0.5, max_neighbors 10, neighbor_distance 50, max_speed 10, avoidance off | 4.7.2 ClassDB |
| 数值 | 实测结果 | 相对于 |
|---|---|---|
| 200 个使用 avoidance 的 bodies | 每帧 1.98 ms,0 对重叠 | M5 Max,fixed fps 60,带 14 个障碍物的 60 m 竞技场 |
| 使用 avoidance 时的扩展能力 | 50 个智能体:1.07 ms,200 个:2.00,800 个:7.31(约每个智能体 9 µs) | 同上 |
| 200 个 server agents 加 MultiMesh | 0.26 ms | 同上 |
| 200 个敌人的思考成本 | 预算 0.40 ms,每 tick 均执行 0.78 ms,不执行 0.33 ms | 5 Hz,每 tick 40 个 |
| 首次 navmesh sync | 3 个 physics frames;rebake 在 2 到 16 个 iterations 后应用 | async iterations 开启(默认) |
| Bake | 5 ms,180 个 polygons | 60 m 竞技场,cell 0.25 |
| 1000 发子弹 | 数据驱动 0.35 ms;带 CCD 的 RigidBody3D 为 1.05 ms;不带 CCD 为 1.00 ms(45% 穿墙) | 60 m/s,生命周期 2 s |
| Jolt 速度限制 | 500 m/s | |
| 地牢生成加验证 | 中位数 88 µs,1000 个中 1000 个有效 | 14-room 主路径,4 个 branches |
| NavigationAgent3D 默认值 | radius 0.5,max_neighbors 10,neighbor_distance 50,max_speed 10,avoidance 关闭 | 4.7.2 ClassDB |
Quality gates
质量门禁
- Measurable: crowd metrics (overlapping pairs, min pair distance, stuck, fell through the floor); ;
scaling_verdict; GUT (budget_share) green after one deliberate red;gd_run.run_testswith 0 parse errors; validators on 1000 seeds; save fixtures; the dialogue compile.check_all - Visual: windowed captures in a SubViewport (160x90 window), with and a contact sheet of 1600 px or less, opened and looked at. Look for crowd spacing round the player, no agents inside obstacles, and the dungeon path from start to boss.
gd_review.image_checks
- 可测量:人群指标(重叠对数、最小成对距离、卡住、掉出地板);;
scaling_verdict;在刻意制造一次失败后,GUT(budget_share)全部通过;gd_run.run_tests报告 0 个解析错误;对 1000 个 seeds 运行 validators;save fixtures;dialogue compile。check_all - 视觉:在 SubViewport 中生成窗口化 captures(160x90 window),使用 ,并生成不超过 1600 px 的 contact sheet,然后打开并实际查看。检查玩家周围的人群间距、是否有智能体进入障碍物内部,以及从起点到 boss 的地牢 path。
gd_review.image_checks
Common mistakes
常见错误
| Mistake | What it looks like | Fix |
|---|---|---|
| Benchmarking plain headless | about 7 ms per "frame" whatever the load | |
| Path queried right after assigning the mesh | empty path, agents idle at spawn | |
| Default bake (Both from root) with NPCs inside | holes round spawn points | group plus static colliders |
| Avoidance off "for speed" | 3108 overlapping pairs, enemies merge | avoidance on: it costs little at 200 |
| Vision as one Area3D per enemy | broadphase churn | distance, cone, one ray [added] |
| Trusting a ray hit on a teleported body | enemy "sees" through a wall | stale-hit distance check |
| Hit areas on layer 1 and mask 1 | self-hits, triple damage | mask or layer only; HitLog |
| "Function blocked during in/out signal" | |
| Bullet bodies on the default layer | 1000 bodies collide: 110 to 170 ms per frame | own layer, mask world and targets |
| No CCD on fast bodies | bullets pass walls at 30 m/s | |
Loading a downloaded | its script runs | |
Default | old values come back | |
| runtime error or a silent no-op through | |
Preloaded inventory | one chest's loot shows in all | |
| Always-succeeding first child in a Selector | the attack branch never runs (Chap.C E_FIy2dTkNc 00:17:27) | gate first, BTProbability or AlwaysFail |
| Logical keycodes in actions | WASD breaks on AZERTY | physical keycodes |
| Teleport with physics interpolation on | the body is drawn sliding across the jump [added, not measured] | |
| no crash in 4.7.2; every later access is a "previously freed" error reading 0 (docs say crash) | never free one; reset its state instead |
| 错误 | 表现 | 修复方式 |
|---|---|---|
| 使用普通 headless 进行基准测试 | 无论负载如何,每个“frame”约耗费 7 ms | |
| 分配 mesh 后立即查询 path | path 为空,智能体停在出生点 | |
| 默认 bake(从 root 解析 Both),且内部存在 NPC | 出生点周围出现孔洞 | 使用 group 和 static colliders |
| 为“速度”而关闭 avoidance | 出现 3108 对重叠,敌人合并在一起 | 开启 avoidance:在 200 个智能体时成本很低 |
| 将每个敌人的 vision 实现为单独 Area3D | 导致 broadphase 频繁抖动 | 使用 distance、cone、单条 ray [added] |
| 信任传送后 body 上的 ray hit | 敌人能够“看见”墙后的目标 | 使用 stale-hit distance check |
| Hit areas 位于 layer 1 且 mask 为 1 | 自我命中,造成三倍伤害 | 只修改 mask 或 layer;使用 HitLog |
在 | 出现“Function blocked during in/out signal” | 使用 |
| Bullet bodies 位于默认 layer | 1000 个 bodies 发生碰撞:每帧 110 到 170 ms | 使用独立 layer,mask world 和 targets |
| 高速 bodies 未启用 CCD | 子弹在 30 m/s 时穿墙 | 使用 |
加载下载的 | 其 script 会被执行 | 使用 |
重新保存后使用默认 | 旧值再次出现 | 使用 |
在 | 出现运行时错误,或通过 | 使用 |
每个箱子都预加载同一个 inventory | 一个箱子的战利品出现在所有箱子中 | 为每个 holder 使用 |
| Selector 的第一个 child 总是成功 | attack branch 永远不会执行(Chap.C E_FIy2dTkNc 00:17:27) | 首先设置 gate,或使用 BTProbability、AlwaysFail |
| Actions 使用 logical keycodes | WASD 在 AZERTY 键盘上失效 | 使用 physical keycodes |
| 启用 physics interpolation 时进行传送 | body 看起来会滑过跳跃过程 [added,未实测] | 移动后调用 |
对 autoload 调用 | 在 4.7.2 中不会崩溃;之后每次访问都会出现“previously freed”错误并读取到 0(docs 称会崩溃) | 永远不要释放它;改为重置其状态 |
Handoffs
交接关系
- Receives: project layout, autoload policy and save model (scenario-godot-architecture); levels with static colliders in and the controller (scenario-godot-3d-world); TileMapLayer navigation (scenario-godot-2d); art from scenario-* skills through those two.
nav_source - Delivers: to scenario-godot-animation; play events and priorities to scenario-godot-audio (mix, buses, attenuation and the listener stay there); inventory signals, dialogue balloon and remap menu to scenario-godot-ui; hit position and normal to scenario-godot-vfx; Resources and pure
state_changedto scenario-godot-multiplayer; benchmark JSON to scenario-godot-performance-export.decide()
- 接收: 项目布局、autoload 策略和存档模型(scenario-godot-architecture);包含 中 static colliders 的关卡及 controller(scenario-godot-3d-world);TileMapLayer 导航(scenario-godot-2d);通过上述两项由 scenario-* skills 提供美术资源。
nav_source - 交付: 向 scenario-godot-animation 提供 ;向 scenario-godot-audio 提供 play events 和 priorities(mix、buses、attenuation 与 listener 保留在该模块中);向 scenario-godot-ui 提供 inventory signals、dialogue balloon 和 remap menu;向 scenario-godot-vfx 提供 hit position 和 normal;向 scenario-godot-multiplayer 提供 Resources 和纯
state_changed;向 scenario-godot-performance-export 提供 benchmark JSON。decide()
Godot 4.7 notes
Godot 4.7 注意事项
- Navigation classes are experimental in 4.7.2. Region and map iterations are async by default, so syncs take several frames. is deprecated: use
region_bake_navigation_meshplusparse_source_geometry_data(or the async variant).bake_from_source_geometry_dataexists.region_get_iteration_idran its callback before returning (P15): it does not move work off the frame.query_path(params, result, callback) - A MultiMesh culls as one box: set (exists) and split big crowds by area.
custom_aabb - The NavigationMesh default is Both (2). Default cell size and height are 0.25.
geometry_parsed_geometry_type - Jolt is the 3D default for new projects from 4.6, but an agent-written project.godot gets GodotPhysics3D unless it sets Jolt (lead's delta).
- copies only file-internal subresources (4.5 and later).
duplicate(true)copies external ones too.duplicate_deep(DEEP_DUPLICATE_ALL) - and
JSON.from_nativeexist; plain JSON numbers come back as floats.to_native - prints "W - Physical". A new InputEventKey has device 16 (
InputEventKey.as_text()).DEVICE_ID_KEYBOARD - Addons: Dialogue Manager is at 4.1.0, where titles are cues; DM3 videos are a version behind. LimboAI 1.8.1 ships a "4.6" GDExtension build that runs on 4.7.2.
- Navigation classes 在 4.7.2 中仍处于 experimental 状态。Region 和 map iterations 默认异步,因此 sync 需要多个 frames。已弃用:请使用
region_bake_navigation_mesh加parse_source_geometry_data,或使用其异步变体。bake_from_source_geometry_data已存在。region_get_iteration_id会在返回前执行 callback(P15):它不会将工作移出当前 frame。query_path(params, result, callback) - MultiMesh 会按照一个 box 进行 culling:请设置 (该属性存在),并按区域拆分大型人群。
custom_aabb - NavigationMesh 的默认 为 Both(2)。默认 cell size 和 height 均为 0.25。
geometry_parsed_geometry_type - 从 4.6 开始,Jolt 是新项目的 3D 默认 physics engine,但如果由 Agent 编写 project.godot 且未显式设置 Jolt,则会使用 GodotPhysics3D。
- 仅复制文件内部的 subresources(4.5 及更高版本)。
duplicate(true)还会复制外部 subresources。duplicate_deep(DEEP_DUPLICATE_ALL) - 存在 和
JSON.from_native;普通 JSON 数字读回后为 floats。to_native - 会输出 "W - Physical"。新的 InputEventKey 的 device 为 16(
InputEventKey.as_text())。DEVICE_ID_KEYBOARD - Addons:Dialogue Manager 当前为 4.1.0,其中 titles 是 cues;DM3 videos 的版本落后一代。LimboAI 1.8.1 随附一个可在 4.7.2 中运行的“4.6”GDExtension build。
References
参考资料
- (P0 to P15 with code and live results),
references/procedures.md(judgment by expert, timestamps),expert-notes.md(rubric),critique.md(editor menus),gui-paths.md(videos, docs, addon hashes).sources.md - : install,
scripts/gd_gameplay.py,run_job,crowd_bench,scaling_verdict, dialogue lint, save scan.budget_share - : nav_tools, arena, crowd_bench, enemy_body, state machine and states, brain, perception, enemy_manager, hitbox, hurtbox, hit_log, combat_layers, bullet_pool, save_io, inventory, quest_rules, dungeon_gen, voice_pool.
scripts/agentkit/gameplay/
- (包含 P0 到 P15、代码和实测结果)、
references/procedures.md(专家判断及时间戳)、expert-notes.md(评分标准)、critique.md(编辑器菜单)、gui-paths.md(视频、文档、addon 哈希)。sources.md - :安装、
scripts/gd_gameplay.py、run_job、crowd_bench、scaling_verdict、dialogue lint、save scan。budget_share - :nav_tools、arena、crowd_bench、enemy_body、state machine 和 states、brain、perception、enemy_manager、hitbox、hurtbox、hit_log、combat_layers、bullet_pool、save_io、inventory、quest_rules、dungeon_gen、voice_pool。
scripts/agentkit/gameplay/