组件

本页面为自动翻译,可能包含错误。如果发现问题,请通过“编辑此页面”链接帮助修正。

组件(component) 是一个普通的 Zig 结构体,通过选择加入编辑器发现机制。无需继承基类,也无需注册样板代码——只需一个标记即可。


将结构体标记为组件

pub const Health = struct {
    pub const is_component = true;

    max: f32 = 100.0,
    current: f32 = 100.0,
};
  • pub const is_component = true; 标记该结构体以供发现。将其设置为 false 可暂时退出而不删除结构体。
  • 编辑器解析真实的 Zig 源代码(而非正则表达式),因此无论格式、注释或条件编译如何,标记都能正常工作。
  • 结构体必须是 pub 的,且名称必须以大写字母开头。
  • 组件类型名称在项目中必须唯一。重复名称会被报告,第二个定义将被忽略。

用户脚本存放在项目的 assets/ 文件夹中。添加或编辑脚本后,点击资源浏览器中的 刷新 以重新扫描。

检查器字段类型

检查器根据字段的 Zig 类型渲染控件:

Zig 类型 检查器控件
f32 带拖动箭头的数字字段
i32 整数字段
bool 复选框
engine.Vec3 带标签的三轴向量
engine.GameObjectRef 拖放目标——从层级面板拖动节点或场景对象
engine.ComponentRef 拖放目标——引用节点上的任意组件
engine.TypedAssetRef(.) 资源选择器——从资源浏览器拖动或使用 ... 按钮
engine.AssetRef 资源选择器——任意资源类型
[N]type(静态数组) 可单独编辑的元素
[]const u8 文本字段

检查器跳过的字段:

  • 私有字段(下划线前缀,如 _internal_state)。
  • 没有默认值的字段(结构体定义中没有 = expr)。
  • comptime 字段。
  • * 指针字段。

可用的生命周期钩子

所有钩子都是可选的。只实现你需要的即可。

钩子 签名 调用时机
awake fn(self) void 组件首次加载时
enable fn(self) void 节点变为活动状态(或组件被添加到活动节点)时
start fn(self) void 场景开始运行时
update fn(self, time: engine.Time) void 每帧——推荐使用 engine.Frame(见下文)
disable fn(self) void 节点变为非活动状态(或组件在销毁前被移除)时
destroy fn(self) void 节点被销毁时

每个钩子也接受 frame: engine.Frame 作为第二个参数。当钩子接受 frame: engine.Frame 时,它可以接收输入、服务、场景树和实用工具:

pub fn update(self: *@This(), frame: engine.Frame) void {
    if (frame.input.wasPressed("jump")) { /* ... */ }
}

这是推荐的签名,因为它提供了脚本所需的一切。

完整的节点生命周期

场景启动时,节点按自上而下的顺序激活。每个节点:

  1. awake —— 按广度优先顺序(父节点先于子节点)在每个组件上调用。
  2. enable —— 按相同顺序调用。
  3. start —— 按相同顺序调用。

然后每帧:

  1. update —— 每帧在每个组件上调用。

关闭时,节点按自下而上的顺序停用:

  1. disable —— 在每个组件上调用。
  2. destroy —— 在每个组件上调用。

运行时添加的组件(在节点已激活后)会立即按顺序获得 awakeenablestart

跨组件的更新顺序

在单个节点内,给定生命周期阶段的钩子按照源代码定义顺序触发——即字段和方法在结构体中出现的顺序。

跨节点之间,顺序由场景层级树决定:父节点先于子节点,同级节点按它们在层级中出现的顺序排列。该顺序在帧和保存之间保持稳定。要重新排序,在层级中拖动节点即可。

自定义更新顺序(例如"所有物理先于所有渲染")已计划但尚未实现。目前请使用树顺序。


← 所有文档 编辑此页面