Godot 的核心抽象:一切游戏对象都是树中的节点。Node(scene/main/node.h,GDCLASS(Node, Object))提供树结构、通知驱动的回调、组、输入路由;SceneTree(scene/main/scene_tree.h:89,继承 MainLoop)驱动每帧更新。
Node
全部状态收在 Data 结构(node.h:199-299):parent/owner/name/tree/viewport/depth/index、HashMap<StringName,Node*> children + children_cache、组数据、进程组与优先级、process/physics_process/input 位域、ready_notified 等。
通知常量(node.h:455-518)
ENTER_TREE=10, EXIT_TREE=11, READY=13, PAUSED=14, PHYSICS_PROCESS=16, PROCESS=17, PARENTED=18, UNPARENTED=19, SCENE_INSTANTIATED=20, POST_ENTER_TREE=27, DISABLED/ENABLED=28/29;另有窗口(1002+)、OS(2009+)、编辑器(9001+)区段。
生命周期传播
_propagate_enter_tree(node.cpp:341-389):继承 tree/depth → viewport = 自身 cast_to<Viewport> 或继承父 → 注册组 → 发 ENTER_TREE → emittree_entered→tree->node_added(this)→ 递归子节点_propagate_ready(node.cpp:323-339):先递归子节点(自底向上 ready) → POST_ENTER_TREE → 首次发 READY 并 emitready- READY 处理(node.cpp:255-280):先按
GDVIRTUAL_IS_OVERRIDDEN自动开启对应 process/input 标志,再GDVIRTUAL_CALL(_ready) - PREDELETE(node.cpp:282-287):清理 owner/owned、从父移除、递归
memdelete子节点;非主线程释放树内节点会被cancel_free拦截
回调全部走通知 + GDVIRTUAL:_ready/_process/_physics_process/_input/_notification 等(node.h:433-444),与 object-model 的通知机制一致。
路径与组
get_node语法(node.cpp:1922-1982):..父、%Name唯一名(查owned_unique_nodes,回退 owner)、普通名查 children HashMap;绝对路径先上溯到根- 组:
add_to_group/remove_from_group/is_in_group;persistent 组随场景保存;SceneTree 按组广播通知/调用(见下) queue_free()转SceneTree::queue_delete(帧末统一释放)- 暂停:
ProcessModeINHERIT/PAUSABLE/WHEN_PAUSED/ALWAYS/DISABLED(node.h:79-85)
SceneTree 主循环
成员:Window *root(:133,即主窗口,继承 Viewport)、current_scene、paused、group_map、delete_queue、process_groups(含默认进程组)。
physics_process(scene_tree.cpp:639-671):flush 变换通知 → emitphysics_frame→ viewport picking →_process(true)→ MessageQueue flush → timers/tweens →_flush_delete_queueprocess(scene_tree.cpp:688-791):multiplayer poll → emitprocess_frame→_process(false)→ 场景切换冲刷 → timers/tweens → delete queue_process_group(scene_tree.cpp:1183-1242):按process_priority排序、拷贝列表防遍历中增删、跳过暂停节点、发 PROCESS 通知- 线程组:SUB_THREAD 组经
_process_groups_thread派发工作线程(scene_tree.cpp:1244) - 组调用:
call_group_flagsp/notify_group_flags,GROUP_CALL_REVERSE/DEFERRED/UNIQUE(UNIQUE 经unique_group_calls去重) - 信号:tree_changed、scene_changed、node_added/node_removed、process_frame、physics_frame
set_pause(scene_tree.cpp:1132):同步停/启 PhysicsServer2D/3D 并下发通知
场景切换
change_scene_to_file → change_scene_to_packed → change_scene_to_node(scene_tree.cpp:1705-1724):移除旧场景记 prev_scene_id,新场景存 pending_new_scene_id;下一帧 process() 中 _flush_scene_change(:1677)memdelete 旧场景、挂载新场景、emit scene_changed。
场景序列化:PackedScene
SceneState : RefCounted(scene/resources/packed_scene.h:38-244)是核心:
- 索引池:
names/variants/node_paths/id_paths(属性值即 Variant,见 variant) NodeData{parent,owner,type,name,instance,index,properties[],groups[]}(:58-73)ConnectionData序列化信号连接(:83-91)base_scene_idx支持场景继承instantiate(GenEditState)(:165)按池还原节点;延迟属性(DeferredNodePathProperties)处理 NodePath 依赖GenEditState:DISABLED/INSTANCE/MAIN/MAIN_INHERITED(编辑器区分主场景编辑态)
PackedScene : Resource(:248-296,扩展名 .scn)仅持有 Ref<SceneState> state;set_bundled_scene(Dictionary) 是文本/二进制格式的交换表示。
Viewport 与输入
Viewport : Node(scene/main/viewport.h:96)持 RenderingServer 视口与 texture_rid;Window 继承 Viewport,SceneTree::root 即 Window*。输入经 _vp_input<viewport_id> 组路由(node.cpp:171-182);GUI 输入在 Viewport::_gui_input_event(viewport.cpp:1931)。渲染侧见 rendering。