实例化场景
本页面为自动翻译,可能包含错误。如果发现问题,请通过“编辑此页面”链接帮助修正。
拥有一个场景(.prefab 文件)后,您可以将其实例化到其他场景中。实例是一个链接副本:对源场景的修改会传播到每个实例,除非实例有意覆盖了某些属性。
术语
- 源 — 磁盘上定义对象树的
.prefab文件。 - 实例 — 该树在已打开场景中的链接副本。
- 覆盖 — 在特定实例上更改的属性,当源更新时这些更改会被保留。
在编辑时实例化
在资源浏览器中,找到场景或预设。有两种实例化方式:
- 将其从资源浏览器拖拽到场景视口或场景层级面板中。
- 右键单击并选择实例化到场景。
新实例出现在场景根节点下,其根节点带有蓝色底色和盒子图标——编辑器以此告诉您它是一个链接副本。
从场景对象创建预设
要将场景中的任何节点转换为可复用的预设:
- 在场景层级中右键单击该节点。
- 选择创建预设。
- 一个
.prefab资源会被写入当前资源浏览器文件夹,该对象成为该预设的第一个实例。
您也可以从层级中拖拽节点并放到资源浏览器上。
编辑预设
在资源浏览器中双击 .prefab 以打开进行编辑。场景层级会显示预设的树。进行更改并保存——下次加载包含实例的场景时,实例会反映您的编辑(保留任何覆盖)。
覆盖
预设实例化后,您可以调整实例上的任何属性——名称、Transform、组件字段。每个更改的属性都会记录为覆盖,并显示在检查器顶部的预设实例横幅中。
横幅有两个操作:
- 还原 — 丢弃此实例上的所有覆盖,并恢复到源预设。
- 应用 — 将实例的当前值推送到源预设中,传播到所有其他实例(每个实例保留其自己的覆盖)。
在运行时生成
游戏代码通过 Frame 上下文生成和销毁链接实例:
const engine = @import("engine");
pub const Spawner = struct {
pub const is_component = true;
prefab: engine.TypedAssetRef(.scene) = .{},
pub fn update(self: *@This(), frame: engine.Frame) void {
if (frame.input.wasPressed("fire")) {
frame.instantiate(self.prefab.slice(), .{ .x = 0, .y = 1, .z = 0 }, null);
}
}
};
frame.instantiate(guid, position, rotation)将新的链接实例排队。position和rotation是根 Transform 的可选覆盖。frame.destroy(node)将移除节点及其后代的操作排队。
两者都是延迟执行的:它们会在当前更新后应用,因此脚本可以在迭代场景对象时生成或销毁对象而不会出现迭代错误。
性能与工作流
实例化不是性能优化——而是工作流优化。您制作一个敌人预设,然后在关卡中放置五十个实例。之后,调整预设的网格或生命值,所有五十个都会更新。实例的运行时成本与手动放置的对象相同。