scenario-godot-gameplay

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Godot 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
--fixed-fps 60
, then look at one capture. If a sibling skill named here is missing from your available skills, ask the user to install it (
npx skills add scenario-labs/skills --skill <name>
); unattended, proceed from tool schemas and flag the gap.
REQUIRED BACKGROUND: scenario-godot-expert (channels,
gd_run
, the review loop, 4.7 traps).
Status (2026-10-02): 16 live tests, the round-2 checks (P15) and the offline suite pass in Godot 4.7.2 (
references/procedures.md
,
tests/code/godot-gameplay/
). Dialogue Manager 4.1.0, LimboAI 1.8.1 and GUT 9.7.1 were run in their own project copies.
目标:Godot 4.7.2.stable,Jolt,macOS Apple Silicon。
在专家水平上,gameplay systems 是一组无需场景即可测试的小型契约:纯决策函数、用于存储数据的 Resources,以及用于发现的 groups。其成本衡量标准是游戏所需的智能体数量,在此之前不会有人争论性能。核心原则是:将规则构建为数据,以
--fixed-fps 60
在 headless 环境中运行,然后查看一次 capture。如果这里提到的某个同级 skill 在可用 skills 中缺失,请要求用户安装(
npx skills add scenario-labs/skills --skill <name>
);在无人值守的情况下,则根据 tool schemas 继续操作并标记该缺口。
必需背景: scenario-godot-expert(channels、
gd_run
、review loop、4.7 traps)。
状态(2026-10-02): 16 项 live tests 已通过;第二轮检查(P15)和 offline suite 在 Godot 4.7.2 中通过(
references/procedures.md
、
tests/code/godot-gameplay/
)。Dialogue Manager 4.1.0、LimboAI 1.8.1 和 GUT 9.7.1 均在各自的项目副本中运行。

Stance (the expert delta)

专家视角的关键差异

  1. Benchmark with
    --fixed-fps 60
    , never plain headless.
    A headless frame sleeps 6.9 ms (
    low_processor_usage_mode_sleep_usec
    ) and runs fewer physics ticks than frames.
    Performance.TIME_*
    monitors 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).
  2. 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
    max_neighbors
    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.
  3. 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
    region_get_iteration_id
    before assigning, wait for it to move, then one more map sync (
    nav_tools.wait_applied
    , P1).
  4. 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).
  5. 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).
  6. 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).
  7. Fast bullets are data, or bodies with CCD. Without
    continuous_cd
    , 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).
  8. A
    .tres
    save is code.
    A GDScript sub_resource runs on load (Godotneers 43BZsLZheA4 01:03:14; reproduced P6). Scan before loading, load with
    CACHE_MODE_IGNORE
    , version and migrate, validate values instead of encrypting (01:01:37).
  1. 使用
    --fixed-fps 60
    进行基准测试,绝不要使用普通 headless。
    headless frame 会休眠 6.9 ms(
    low_processor_usage_mode_sleep_usec
    ),其 physics tick 数量少于 frame 数量。
    Performance.TIME_*
    monitors 约每秒刷新一次,在 fixed fps 下读取结果为 0。测量每帧的 wall milliseconds,取 3 次结果的中位数,并比较同一次运行中的 A/B 对(实测值,P0)。
  2. 人群并不是 baseline 所认为的瓶颈。 在 M5 Max 上,200 个使用 NavigationAgent3D avoidance 的 CharacterBody3D 敌人每帧约耗费 2 ms。成本随智能体数量线性增长到 800 个(7.3 ms),而在 200 个时,avoidance 本身仍处于噪声范围内。调整
    max_neighbors
    或 repath interval 没有带来可测量的收益。avoidance 带来的价值是正确性:不开启时检测到 3108 对重叠,而开启后为 0(P2)。只有在智能体不需要节点时,才改用 server agents 加一个 MultiMesh(200 个为 0.26 ms)。
  3. 等待你分配的 mesh,而不是等待“the map”。 文档要求等待一个 physics frame。实际运行时,第一次同步用了 3 个 frame。重新 bake 后,map id 发生了变化,而 region 仍在提供旧 polygons。先读取
    region_get_iteration_id
    再进行分配,等待其发生变化,然后再执行一次 map sync(
    nav_tools.wait_applied
    ,P1)。
  4. 从一组 static colliders 执行 bake。 新建的 NavigationMesh 会从 region 的 children 中解析 Both(meshes 和 colliders),因此位于 region 下的 NPC 会在地图上挖出一个 3 m 的孔洞(Bramwell 2W4JP48oZ8U 00:12:37;实测值 P1)。
  5. 根据决定性条件选择 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)。
  6. Hitboxes 使用 mask,hurtboxes 使用 layer,每次挥击只生成一个 HitLog(Queble cX-vzfmzjnE 00:06:36、00:12:55)。新建的 Area 默认位于 layer 1 且 mask 为 1,会命中自身的 owner(P4)。
  7. 高速子弹要么采用数据驱动,要么使用带 CCD 的 bodies。 没有
    continuous_cd
    时,即使速度为 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)。
  8. .tres
    存档本质上就是代码。
    加载时,GDScript sub_resource 会被执行(Godotneers 43BZsLZheA4 01:03:14;已复现 P6)。加载前先进行扫描,使用
    CACHE_MODE_IGNORE
    加载,添加 version 并执行 migrate,验证数值,而不是加密(01:01:37)。

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
    target_position
    .
    With avoidance on and no target,
    safe_velocity
    stayed 0 for 30 ticks; with a target it returned the full 3 m/s.
  • Avoidance never feeds pathfinding. Agents are circles with no navmesh or physics knowledge, so walls still come from the path (docs).
  • One
    get_next_path_position()
    per physics frame, and none after the end.
    Once
    is_navigation_finished()
    is true it still returns the last point (0.93 m away here): stop steering there, or the agent creeps.
  • path_desired_distance
    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.
  • Defaults:
    time_horizon_agents
    1.0,
    time_horizon_obstacles
    0.0. Lower the horizon if agents slow down too early. Too few
    max_neighbors
    and avoidance is ignored (docs; not measured here).
除非另有标记,以下结果均在 4.7.2 中实测:
  • Avoidance 需要
    target_position
    。
    开启 avoidance 却没有 target 时,
    safe_velocity
    在 30 个 tick 中始终为 0;设置 target 后,它恢复为完整的 3 m/s。
  • Avoidance 永远不会反馈给 pathfinding。 Agents 是 circles,不具备 navmesh 或 physics 知识,因此墙体仍来自 path(docs)。
  • 每个 physics frame 调用一次
    get_next_path_position()
    ,路径结束后不要再调用。
    一旦
    is_navigation_finished()
    为 true,它仍会返回最后一个点(此处距离目标 0.93 m):应在此停止 steering,否则智能体会缓慢爬行。
  • path_desired_distance
    必须大于一个 tick 的移动距离,并大于 navmesh 相对地面的悬浮高度(约 0.3 m)。
    在 25 m/s(每 tick 0.42 m)且阈值为 0.1 时,智能体在 1800 个 tick 中的 1782 个都在反向移动,始终无法到达;阈值为 1.0 时,它在 182 个 tick 后到达。若阈值为 0.1 且脚部测得高度等于地面,它甚至无法离开第一个路径点。
  • 默认值:
    time_horizon_agents
    为 1.0,
    time_horizon_obstacles
    为 0.0。如果智能体过早减速,应降低 horizon。
    max_neighbors
    太少时,avoidance 会被忽略(docs;此处未实测)。

Establish first

首先确定

InputWhy it changes the planDefault
Agent count on screennodes vs server agents, think budget200
Frame budget for gameplaythe gate for every benchmarka quarter of 16.67 ms (4.2 ms) at 60 fps [added]
2D or 3DNavigationAgent2D vs 3D, Area2D vs 3D3D
Who authors behaviorcode (FSM, enum) vs designers (LimboAI)code
Save trustown files only vs shared or modded savesshared: scan or JSON
Platforminput devices, CPU budgetdesktop, keyboard and mouse plus pad
输入为什么会改变方案默认值
屏幕上的智能体数量使用 nodes 还是 server agents,以及思考预算200
gameplay 的帧预算所有基准测试的门限60 fps 下 16.67 ms 的四分之一(4.2 ms)[added]
2D 或 3DNavigationAgent2D 与 3D、Area2D 与 3D3D
谁编写行为code(FSM、enum)还是设计师(LimboAI)code
存档信任级别仅信任自己的文件,还是信任共享或 modded 存档共享:扫描或使用 JSON
平台输入设备、CPU 预算桌面端、键盘和鼠标以及手柄

Workflow

工作流

  1. Set up the project.
    • Clone Base3D with
      gd_env.base_project("3d", P)
      and give it its own
      application/config/name
      , because clones otherwise share
      user://
      . Run
      gg.install(P)
      .
    • GATE: project.godot has
      3d/physics_engine="Jolt Physics"
      and a stated renderer;
      gd_run.check_all(P)
      reports 0 parse errors.
  2. Level navigation.
    • Static geometry goes in group
      nav_source
      . Build the mesh with
      make_navmesh(parsed colliders, source group)
      , then
      bake
      , then
      wait_applied
      .
    • GATE:
      map_get_path
      between sample points is non-empty with 0 obstacle crossings; the polygon count is above 0; no hole at NPC spawns (P1).
  3. Movement and the crowd.
    • Enable avoidance;
      velocity_computed
      drives
      move_and_slide
      ; repath is throttled; steering is XZ only.
    • Run
      gg.crowd_bench(P, n)
      at 50, 200 and 800, then
      gg.scaling_verdict
      . In your own benchmark scene, log
      Performance.add_custom_monitor(&"ai/thinks", callable)
      and
      OBJECT_ORPHAN_NODE_COUNT
      beside wall time (it read 5 after 5 stray
      Node.new()
      , P15).
    • GATE: 0 overlapping pairs; exponent under 1.3; the median at the target count fits the gameplay budget (
      gg.budget_share
      ); the orphan count is flat. Then a windowed capture of the crowd, opened.
  4. AI.
    • Write the brain as
      decide(state, percept)
      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
      VisibleOnScreenNotifier3D.is_on_screen()
      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.
    • 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).
  5. 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
      bullet_pool
      ; bouncing objects are RigidBody3D with CCD.
    • 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).
  6. Persistence.
    • Typed save Resource with VERSION and
      migrate()
      ,
      save_io.save_resource_atomic
      ,
      load_resource_checked
      ; inventories duplicated per holder.
    • GATE: round trip equal; every old fixture loads; the evil fixture is refused; the cache test passes (P6, P7).
  7. Dialogue and quests.
    • Dialogue Manager 4.x
      .dialogue
      files; quest order is turn in, then continue, then offer.
    • GATE: the import compiles every file with 0 errors;
      gg.check_dialogue_text
      finds no missing cue; a headless walk reaches each branch and mutates state (P8).
  8. Input.
    • Physical-key actions; gameplay in
      _unhandled_input
      ; remaps go to a ConfigFile.
    • GATE: synthetic press and just-pressed tests pass; the STOP panel consumes a pushed click; the remap survives a reload (P10).
  9. Procedural content.
    • Seeded data first (
      dungeon_gen
      ), validators, then geometry, bake and path.
    • 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).
  10. Wrap up.
    • Run
      test_gameplay_live.py
      and copy the evidence. Score yourself against
      references/critique.md
      .
  1. 设置项目。
    • 使用
      gd_env.base_project("3d", P)
      克隆 Base3D,并为其设置独立的
      application/config/name
      ,因为克隆项目默认共享
      user://
      。运行
      gg.install(P)
      。
    • GATE:project.godot 中包含
      3d/physics_engine="Jolt Physics"
      和已声明的 renderer;
      gd_run.check_all(P)
      报告 0 个解析错误。
  2. 关卡导航。
    • 将静态几何体放入 group
      nav_source
      。使用
      make_navmesh(parsed colliders, source group)
      构建 mesh,然后依次执行
      bake
      和
      wait_applied
      。
    • GATE:采样点之间的
      map_get_path
      非空且没有穿越障碍物;polygon 数量大于 0;NPC 出生点处没有孔洞(P1)。
  3. 移动与人群。
    • 启用 avoidance;由
      velocity_computed
      驱动
      move_and_slide
      ;对 repath 进行节流;steering 仅限 XZ。
    • 在 50、200 和 800 个智能体时分别运行
      gg.crowd_bench(P, n)
      ,然后运行
      gg.scaling_verdict
      。在自有 benchmark scene 中,将
      Performance.add_custom_monitor(&"ai/thinks", callable)
      和
      OBJECT_ORPHAN_NODE_COUNT
      与 wall time 一起记录(在 5 次遗留
      Node.new()
      后该值为 5,P15)。
    • GATE:重叠对数为 0;指数低于 1.3;目标数量下的中位耗时符合 gameplay 预算(
      gg.budget_share
      );orphan 数量保持稳定。然后打开人群的窗口化 capture。
  4. AI。
    • 使用 hysteresis 编写
      decide(state, percept)
      brain。优先采用低成本 perception(距离、cone、一条 ray、stale-hit check)。manager 以约 5 Hz 思考,并设置每个 tick 的上限。远距离敌人应减少思考:按距离平方划分 tier,因为
      VisibleOnScreenNotifier3D.is_on_screen()
      在 headless 环境中始终为 false,而基准测试会将所有敌人放入 far tier(P15)。node FSM 用于主角;如果由设计师编写行为,则使用 LimboAI。
    • GATE:GUT transition table 全部通过;主角场景历史符合预期顺序(
      patrol
      、
      chase
      、
      attack
      、
      chase
      、
      search
      、
      patrol
      );已测量思考成本的 A/B 对比(P3、P9、P13)。
  5. 战斗。
    • 为 layers 命名(World 1、Player 2、Enemy 3、PlayerHurtbox 5、EnemyHurtbox 6、Projectile 7)。使用 kit 中的 hitbox 和 hurtbox。子弹通过
      bullet_pool
      处理;需要反弹的 objects 使用带 CCD 的 RigidBody3D。
    • GATE:使用 shared log 的挥击计为 1 次命中;同阵营计为 0;最高速度下的 tunnelling test 结果为 8 发中 0 发穿墙;子弹位于自己的 layer(P4、P5)。
  6. 持久化。
    • 使用带 VERSION 和
      migrate()
      的 typed save Resource,并使用
      save_io.save_resource_atomic
      、
      load_resource_checked
      ;每个 holder 的 inventories 都要单独复制。
    • GATE:往返结果一致;所有旧 fixtures 均可加载;恶意 fixture 被拒绝;cache test 通过(P6、P7)。
  7. 对话与任务。
    • 使用 Dialogue Manager 4.x 的
      .dialogue
      文件;任务顺序为先 turn in,再 continue,最后 offer。
    • GATE:import 编译所有文件且 0 个错误;
      gg.check_dialogue_text
      未发现缺失的 cue;headless walk 到达每个 branch 并改变状态(P8)。
  8. 输入。
    • Actions 使用 physical keys;gameplay 放在
      _unhandled_input
      中;remaps 写入 ConfigFile。
    • GATE:synthetic press 和 just-pressed tests 通过;STOP 面板会消费按下的点击事件;remap 在重新加载后仍然有效(P10)。
  9. 程序化内容。
    • 先生成 seeded data(
      dungeon_gen
      ),再运行 validators,之后生成 geometry、bake 和 path。
    • GATE:1000 个 seeds 产生 0 个 validator failures;相同 seed 产生相同 hash;从起点到 boss 的 path 存在;打开俯视 capture(P11)。
  10. 收尾。
    • 运行
      test_gameplay_live.py
      并复制证据。根据
      references/critique.md
      对自身进行评分。

Numbers

数值

ValueMeasuredRelative to
200 bodies with avoidance1.98 ms per frame, 0 overlapsM5 Max, fixed fps 60, 60 m arena with 14 obstacles
Scaling with avoidance50 agents: 1.07 ms, 200: 2.00, 800: 7.31 (about 9 µs per agent)same
200 server agents plus MultiMesh0.26 mssame
Think cost, 200 enemiesbudget 0.40 ms, every tick 0.78, none 0.335 Hz, 40 per tick
First navmesh sync3 physics frames; rebake applied after 2 to 16async iterations on (default)
Bake5 ms, 180 polygons60 m arena, cell 0.25
1000 bulletsdata 0.35 ms; RigidBody3D with CCD 1.05; without CCD 1.00 (45% miss walls)60 m/s, 2 s life
Jolt speed clamp500 m/s
physics/jolt_physics_3d/limits/max_linear_velocity
Dungeon generate plus validate88 µs median, 1000 of 1000 valid14-room main path, 4 branches
NavigationAgent3D defaultsradius 0.5, max_neighbors 10, neighbor_distance 50, max_speed 10, avoidance off4.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 加 MultiMesh0.26 ms同上
200 个敌人的思考成本预算 0.40 ms,每 tick 均执行 0.78 ms,不执行 0.33 ms5 Hz,每 tick 40 个
首次 navmesh sync3 个 physics frames;rebake 在 2 到 16 个 iterations 后应用async iterations 开启(默认)
Bake5 ms,180 个 polygons60 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
physics/jolt_physics_3d/limits/max_linear_velocity
地牢生成加验证中位数 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
    ;
    budget_share
    ; GUT (
    gd_run.run_tests
    ) green after one deliberate red;
    check_all
    with 0 parse errors; validators on 1000 seeds; save fixtures; the dialogue compile.
  • Visual: windowed captures in a SubViewport (160x90 window), with
    gd_review.image_checks
    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.
  • 可测量:人群指标(重叠对数、最小成对距离、卡住、掉出地板);
    scaling_verdict
    ;
    budget_share
    ;在刻意制造一次失败后,GUT(
    gd_run.run_tests
    )全部通过;
    check_all
    报告 0 个解析错误;对 1000 个 seeds 运行 validators;save fixtures;dialogue compile。
  • 视觉:在 SubViewport 中生成窗口化 captures(160x90 window),使用
    gd_review.image_checks
    ,并生成不超过 1600 px 的 contact sheet,然后打开并实际查看。检查玩家周围的人群间距、是否有智能体进入障碍物内部,以及从起点到 boss 的地牢 path。

Common mistakes

常见错误

MistakeWhat it looks likeFix
Benchmarking plain headlessabout 7 ms per "frame" whatever the load
--fixed-fps 60
Path queried right after assigning the meshempty path, agents idle at spawn
wait_applied
Default bake (Both from root) with NPCs insideholes round spawn pointsgroup plus static colliders
Avoidance off "for speed"3108 overlapping pairs, enemies mergeavoidance on: it costs little at 200
Vision as one Area3D per enemybroadphase churndistance, cone, one ray [added]
Trusting a ray hit on a teleported bodyenemy "sees" through a wallstale-hit distance check
Hit areas on layer 1 and mask 1self-hits, triple damagemask or layer only; HitLog
monitoring = false
in
area_entered
"Function blocked during in/out signal"
set_deferred
Bullet bodies on the default layer1000 bodies collide: 110 to 170 ms per frameown layer, mask world and targets
No CCD on fast bodiesbullets pass walls at 30 m/s
continuous_cd
or ray-swept data
Loading a downloaded
.tres
its script runs
load_resource_checked
or JSON with
from_native
Default
load()
after re-saving
old values come back
CACHE_MODE_IGNORE
save.items = [...]
on
Array[String]
runtime error or a silent no-op through
set()
items.assign([...])
Preloaded inventory
.tres
on every chest
one chest's loot shows in all
duplicate(true)
per holder
Always-succeeding first child in a Selectorthe attack branch never runs (Chap.C E_FIy2dTkNc 00:17:27)gate first, BTProbability or AlwaysFail
Logical keycodes in actionsWASD breaks on AZERTYphysical keycodes
Teleport with physics interpolation onthe body is drawn sliding across the jump [added, not measured]
reset_physics_interpolation()
after the move (method exists)
queue_free()
on an autoload
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
--fixed-fps 60
分配 mesh 后立即查询 pathpath 为空,智能体停在出生点
wait_applied
默认 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
在
area_entered
中设置
monitoring = false
出现“Function blocked during in/out signal”使用
set_deferred
Bullet bodies 位于默认 layer1000 个 bodies 发生碰撞:每帧 110 到 170 ms使用独立 layer,mask world 和 targets
高速 bodies 未启用 CCD子弹在 30 m/s 时穿墙使用
continuous_cd
或 ray-swept data
加载下载的
.tres
其 script 会被执行使用
load_resource_checked
,或使用带
from_native
的 JSON
重新保存后使用默认
load()
旧值再次出现使用
CACHE_MODE_IGNORE
在
Array[String]
上使用
save.items = [...]
出现运行时错误,或通过
set()
静默无效
使用
items.assign([...])
每个箱子都预加载同一个 inventory
.tres
一个箱子的战利品出现在所有箱子中为每个 holder 使用
duplicate(true)
Selector 的第一个 child 总是成功attack branch 永远不会执行(Chap.C E_FIy2dTkNc 00:17:27)首先设置 gate,或使用 BTProbability、AlwaysFail
Actions 使用 logical keycodesWASD 在 AZERTY 键盘上失效使用 physical keycodes
启用 physics interpolation 时进行传送body 看起来会滑过跳跃过程 [added,未实测]移动后调用
reset_physics_interpolation()
(该方法存在)
对 autoload 调用
queue_free()
在 4.7.2 中不会崩溃;之后每次访问都会出现“previously freed”错误并读取到 0(docs 称会崩溃)永远不要释放它;改为重置其状态

Handoffs

交接关系

  • Receives: project layout, autoload policy and save model (scenario-godot-architecture); levels with static colliders in
    nav_source
    and the controller (scenario-godot-3d-world); TileMapLayer navigation (scenario-godot-2d); art from scenario-* skills through those two.
  • Delivers:
    state_changed
    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
    decide()
    to scenario-godot-multiplayer; benchmark JSON to scenario-godot-performance-export.
  • 接收: 项目布局、autoload 策略和存档模型(scenario-godot-architecture);包含
    nav_source
    中 static colliders 的关卡及 controller(scenario-godot-3d-world);TileMapLayer 导航(scenario-godot-2d);通过上述两项由 scenario-* skills 提供美术资源。
  • 交付: 向 scenario-godot-animation 提供
    state_changed
    ;向 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 和纯
    decide()
    ;向 scenario-godot-performance-export 提供 benchmark JSON。

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.
    region_bake_navigation_mesh
    is deprecated: use
    parse_source_geometry_data
    plus
    bake_from_source_geometry_data
    (or the async variant).
    region_get_iteration_id
    exists.
    query_path(params, result, callback)
    ran its callback before returning (P15): it does not move work off the frame.
  • A MultiMesh culls as one box: set
    custom_aabb
    (exists) and split big crowds by area.
  • The NavigationMesh default
    geometry_parsed_geometry_type
    is Both (2). Default cell size and height are 0.25.
  • 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).
  • duplicate(true)
    copies only file-internal subresources (4.5 and later).
    duplicate_deep(DEEP_DUPLICATE_ALL)
    copies external ones too.
  • JSON.from_native
    and
    to_native
    exist; plain JSON numbers come back as floats.
  • InputEventKey.as_text()
    prints "W - Physical". A new InputEventKey has device 16 (
    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
    已存在。
    query_path(params, result, callback)
    会在返回前执行 callback(P15):它不会将工作移出当前 frame。
  • MultiMesh 会按照一个 box 进行 culling:请设置
    custom_aabb
    (该属性存在),并按区域拆分大型人群。
  • NavigationMesh 的默认
    geometry_parsed_geometry_type
    为 Both(2)。默认 cell size 和 height 均为 0.25。
  • 从 4.6 开始,Jolt 是新项目的 3D 默认 physics engine,但如果由 Agent 编写 project.godot 且未显式设置 Jolt,则会使用 GodotPhysics3D。
  • duplicate(true)
    仅复制文件内部的 subresources(4.5 及更高版本)。
    duplicate_deep(DEEP_DUPLICATE_ALL)
    还会复制外部 subresources。
  • 存在
    JSON.from_native
    和
    to_native
    ;普通 JSON 数字读回后为 floats。
  • InputEventKey.as_text()
    会输出 "W - Physical"。新的 InputEventKey 的 device 为 16(
    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

参考资料

  • references/procedures.md
    (P0 to P15 with code and live results),
    expert-notes.md
    (judgment by expert, timestamps),
    critique.md
    (rubric),
    gui-paths.md
    (editor menus),
    sources.md
    (videos, docs, addon hashes).
  • scripts/gd_gameplay.py
    : install,
    run_job
    ,
    crowd_bench
    ,
    scaling_verdict
    ,
    budget_share
    , dialogue lint, save scan.
  • scripts/agentkit/gameplay/
    : 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.
  • references/procedures.md
    (包含 P0 到 P15、代码和实测结果)、
    expert-notes.md
    (专家判断及时间戳)、
    critique.md
    (评分标准)、
    gui-paths.md
    (编辑器菜单)、
    sources.md
    (视频、文档、addon 哈希)。
  • scripts/gd_gameplay.py
    :安装、
    run_job
    、
    crowd_bench
    、
    scaling_verdict
    、
    budget_share
    、dialogue lint、save scan。
  • scripts/agentkit/gameplay/
    :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。