教程
本页面为自动翻译,可能包含错误。如果发现问题,请通过“编辑此页面”链接帮助修正。
本教程将引导您打开示例项目、编写脚本组件并构建您的第一款游戏。
1. 启动编辑器
zig build run
Turian Studio 将打开一个默认场景(地面、摄像机、方向光)。
2. 打开示例项目
- 选择 文件 → 打开项目…
- 导航到
examples/basic-project/并确认。 - 资源浏览器显示项目的
assets/文件夹。 - 双击
scene-01.prefab加载场景。
3. 编辑器布局
┌──────────────┬──────────────────────┬────────────────┐
│ 场景 │ 场景视图 │ 检查器 │
│ 层级 │ (3D 视口) │ │
├──────────────┴──────────────────────┴────────────────┤
│ 资源浏览器 │
└───────────────────────────────────────────────────────┘
- 场景层级 — 每个游戏对象;单击选择,拖拽重新排序。
- 场景视图 — 实时 3D 预览(SDL3 GPU — Vulkan/Metal/D3D12)。
- 检查器 — 编辑选中对象的 Transform 和组件字段。
- 资源浏览器 — 浏览
assets/;双击.prefab场景文件打开。
4. 添加游戏对象
- 场景 → 添加空对象(或点击菜单项)。
- 在层级中选中它。
- 在检查器中,展开 Transform 并将位置设置为
(0, 1, 0)。 - 点击 添加组件 ▾ → MeshRenderer。
5. 编写脚本组件
在项目文件夹内创建 assets/spinner.zig:
const engine = @import("engine");
pub const Spinner = struct {
/// Marks this struct as a component the editor should discover.
pub const is_component = true;
/// Rotation speed in degrees per second (editable in Inspector).
speed: f32 = 90.0,
pub fn awake(self: *Spinner) void {
_ = self;
@import("std").debug.print("[Spinner] awake\n", .{});
}
pub fn update(self: *Spinner, time: engine.Time) void {
_ = self.speed * time.delta; // apply rotation once scene API lands
}
};
关键规则:
- 在结构体内部添加
pub const is_component = true;标记以便被发现。编辑器解析 Zig 源码(非正则表达式),因此无论格式、注释或条件编译如何,标记都有效。设置为false可临时将结构体排除在外。 - 结构体必须是
pub的,且名称以大写字母开头。 - 每个组件类型名称在项目中必须是唯一的——重复的名称会被报告,第二个将被忽略。
- 支持的字段类型:
f32、i32、bool、engine.Vec3、engine.GameObjectRef、engine.ComponentRef、engine.AssetRef。
点击资源浏览器标题栏中的刷新以加载新脚本,然后通过添加组件 ▾ 添加 Spinner。
6. 脚本生命周期钩子
所有钩子都是可选的——只需实现您需要的:
| 钩子 | 调用时机 |
|---|---|
awake(self) |
对象首次加载时 |
enable(self) |
对象变为活跃时 |
start(self) |
场景开始运行时 |
update(self, frame: engine.Frame) |
每帧 (推荐) |
update(self, time: engine.Time) |
每帧 (旧版) |
disable(self) |
对象变为非活跃时 |
destroy(self) |
对象被销毁时 |
所有钩子也接受 frame: engine.Frame 作为第二参数——使用 update(self, frame: engine.Frame) 来访问输入、服务和完整的场景上下文。详见输入系统指南。
engine.Time 字段(也可通过 frame.time 访问):
.delta— 自上一帧以来的秒数(f32).elapsed— 自场景启动以来的总秒数(f32).frame— 帧计数器(u64)
FPS 计数器示例
const std = @import("std");
const engine = @import("engine");
pub const FpsDisplay = struct {
pub const is_component = true;
_timer: f32 = 0,
pub fn update(self: *FpsDisplay, time: engine.Time) void {
self._timer += time.delta;
if (self._timer >= 1.0) {
self._timer -= 1.0;
const fps = if (time.delta > 0) 1.0 / time.delta else 0.0;
std.debug.print("FPS: {d:.0}\n", .{fps});
}
}
};
对象引用示例
const engine = @import("engine");
pub const Follower = struct {
pub const is_component = true;
/// Drag a game object from the Hierarchy onto this field.
target: engine.GameObjectRef = .{},
pub fn start(self: *Follower) void {
const name = self.target.slice();
if (name.len > 0) {
@import("std").debug.print("[Follower] following '{s}'\n", .{name});
}
}
};
7. 保存场景
文件 → 保存场景 将写入 assets/scene-01.prefab——一个人类可读的 JSON 文件,您可以进行差异对比并提交到 Git。
8. 构建游戏
通过编辑器
构建 → 构建游戏 将独立可执行文件编译到项目文件夹内的 .cache/zig-out/bin/game。
通过 CLI
zig build cli -- build path/to/my-project
或使用安装好的二进制文件:
turian-cli build path/to/my-project
turian-cli new-project ../my-new-game "My Game" # 创建项目
turian-cli info path/to/my-project # 打印元数据
9. 使用数学库
const math = @import("engine").math;
const pos = math.Vector3{ .x = 0, .y = 1, .z = 0 };
const rot = math.Quaternion.fromAxisAngle(math.Vector3.up(), 45.0);
const m = rot.toMatrix4();
const col = math.Vector3i{ .x = 255, .y = 128, .z = 0 }; // integer vector
可用类型:Vector2、Vector3、Vector4、Vector2i、Vector3i、Vector4i、Matrix4、Quaternion。
下一步
- 阅读安装 / 从源码构建以了解完整的开发者设置。
- 浏览[示例文件夹]({{ site.Params.Repo }}/-/tree/main/examples)获取更多完整的项目模板。
- 查看输入系统指南以添加动作映射、游戏手柄支持和运行时重绑定。
- 在检查器中查看组件字段参考——将鼠标悬停在任何字段标签上可查看其类型信息。