【Godot】【入门】节点生命周期怎么用(避免帧循环乱写导致卡顿的范式)

许多新手把逻辑全塞进 _process,结果卡顿、逻辑乱序。本文拆解 Godot 节点生命周期:加载、就绪、物理帧、普通帧、输入、退出,并给出"放哪写什么"的范式与性能建议。

核心概念速览

  • _ready():节点进入场景树后调用一次,适合初始化、找子节点、连接信号。
  • _process(delta):每帧(受 fps 影响)执行,适合与显示相关、非物理逻辑。
  • _physics_process(delta):固定频率(默认 60Hz)执行,适合运动、碰撞计算。
  • _input(event):原始输入事件回调,UI 可能拦截。
  • _unhandled_input(event):UI 未消费的输入才会来到此处,适合游戏全局输入。
  • _exit_tree() / _notification:节点从树中移除/销毁时触发,用于解绑、保存。

心法:运动/碰撞放 _physics_process,视觉/插值放 _process,初始化放 _ready,输入优先 _unhandled_input

生命周期顺序(常见调用链)

  1. 构造脚本(_init 可选)。
  2. 进入场景树 → _enter_tree_ready
  3. 每帧: _process_physics_process 按引擎节奏交替。
  4. 输入事件 _input → UI → _unhandled_input
  5. 离开场景树:_exit_treequeue_free 清理资源。

各阶段写什么

_ready:初始化、连接、查找

gdscript 复制代码
@onready var anim := $AnimationPlayer
func _ready():
    anim.play("idle")
    $Area2D.body_entered.connect(_on_body_entered)
  • 不要在 _init 里找节点,场景尚未装配。
  • 导出变量在此安全使用。

_process:视觉/插值/计时

gdscript 复制代码
func _process(delta):
    sprite.modulate = sprite.modulate.lerp(Color.WHITE, 0.1)
    ui_time += delta
    label.text = format_time(ui_time)
  • 不要在这里做碰撞运算,避免 fps 变化导致穿透。

_physics_process:运动与碰撞

gdscript 复制代码
func _physics_process(delta):
    velocity.y += gravity * delta
    move_and_slide()
  • 使用 move_and_slide/move_and_collide 等物理 API,保证稳定性。
  • 粒度:只放必须的物理计算,其他逻辑分层。

输入处理:_input vs _unhandled_input

  • UI 项目:优先 _unhandled_input,避免与按钮焦点冲突。
gdscript 复制代码
func _unhandled_input(event):
    if event.is_action_pressed("pause"):
        toggle_pause()
        get_viewport().set_input_as_handled()
  • 需要原始鼠标移动(如相机)的放 _input

退出与清理:_exit_tree

gdscript 复制代码
func _exit_tree():
    SignalsBus.enemy_spawned.disconnect(_on_enemy_spawned)
  • 解绑全局信号/计时器,释放引用避免内存泄漏。

常见坑与规避

  • 把物理放在 _process :fps 波动导致速度不稳甚至穿透;改用 _physics_process
  • 在 _ready 前访问节点null instance 报错;改用 @onready 或放到 _ready
  • 重复 connect :在 _process 里连接信号会导致多次绑定;连接操作放 _ready,必要时先 disconnect
  • 忘记 queue_free :动态实例不释放导致泄漏;场景切换时用 queue_freecall_deferred("free")
  • 输入被 UI 吃掉 :把核心输入监听放 _unhandled_input,或在 _input 调用 accept_event()

性能小贴士

  • 减少每帧分配:在 _process 内避免频繁创建对象(如 new Vector2),可复用向量或在类成员预存。
  • 频繁逻辑分级:高频逻辑 _physics_process,中频逻辑用 Timer,低频逻辑用 yield/await 或状态机驱动。
  • 关闭未用的处理:set_process(false)set_physics_process(false) 关闭回调,UI 场景静态时尤为有效。

模板:角色控制器的分层

gdscript 复制代码
func _ready():
    _init_inputs()
    _init_signals()

func _physics_process(delta):
    _update_gravity(delta)
    _update_move(delta)
    _apply_motion()

func _process(delta):
    _update_animations(delta)
    _update_ui(delta)
  • 物理与表现分开,方便调试;动画跟随状态,不直接写在物理段。

调试生命周期顺序

  • 打印顺序:在各回调 print,运行一次即可确认调用次序。
  • 调试器 → Monitors → Frame Time 观察 _process_physics_process 是否被启用。
  • Remote SceneTree 查看节点是否已经进入场景树。

总结复盘

  • 分三类:初始化 _ready,物理 _physics_process,表现 _process,输入 _unhandled_input,清理 _exit_tree
  • 避免把所有逻辑塞进 _process;关闭不需要的处理;信号连接放 _ready,解绑放 _exit_tree
  • 掌握这些生命周期范式,能让脚本结构更清晰、性能更稳,不再因为帧循环乱写导致卡顿。
相关推荐
mxwin6 小时前
Unity Shader 跨平台兼容性:处理纹理坐标翻转与精度差异
unity·游戏引擎
王家视频教程图书馆7 小时前
godot 下载地址
游戏引擎·godot
small-pudding11 小时前
Unity URP + Compute Shader 路径追踪器实战:从可用到可优化
unity·游戏引擎
weixin_4239950011 小时前
unity 物体转向鼠标点击方向2d和3d
unity·计算机外设·游戏引擎
mxwin11 小时前
Unity URP 下 Shader 变体 (Variants):multi_compile 与 shader_feature的关键字管理及变体爆炸防控策略
unity·游戏引擎
RReality13 小时前
【Unity Shader URP】全息扫描线(Hologram Scanline)源码+脚本控制
ui·unity·游戏引擎·图形渲染
渔民小镇14 小时前
一次编写到处对接 —— 为 Godot/Unity/React 生成统一交互接口
java·分布式·游戏·unity·godot
RReality1 天前
【Unity Shader URP】序列帧动画(Sprite Sheet)实战教程
unity·游戏引擎
mxwin1 天前
Unity URP 多线程渲染:理解 Shader 变体对加载时间的影响
unity·游戏引擎·shader
呆呆敲代码的小Y1 天前
【Unity工具篇】| 游戏完整资源热更新流程,YooAsset官方示例项目
人工智能·游戏·unity·游戏引擎·热更新·yooasset·免费游戏