Table of Contents

使用预制体

中级 程序员 设计师

要实例化预制体,请将其从资产视图拖放到场景中。

你可以像处理其他实体一样重新编排预制体实例中的实体:

  • 创建子级和父级实体
  • 拖入实体,将其添加到预制体实例中
  • 将实体从预制体实例中拖出,使其成为独立实体

管理预制体父级实体

默认情况下,Game Studio 会创建一个空的父级实体,并将预制体的实体作为其子级。实体树会在子级实体旁边以绿色显示预制体父级的名称。

实体树中的预制体父级与子级

这样做的好处是可以将预制体的实体作为一组进行管理,并保持它们的相对位置。例如,假设你有一个由多个实体(车身、座椅、四个车轮等)组装而成的汽车预制体。当你在场景中移动这辆车时,你希望它的各个组件实体保持成组状态。这可以通过移动预制体的父级实体来实现。

如果你不想为预制体创建父级实体,请在将预制体放入场景时按住 Alt。当你不关心预制体各实体的相对位置、也不需要将它们作为一组一起移动时,这很有用。例如,假设你的预制体由几个随机摆放的板条箱实体组成。放置之后,板条箱之间是否保持相对位置并不重要;事实上,好几堆一模一样的"随机摆放"的板条箱看起来反而很不自然。

在这种情况下,父级实体是不必要的。相反,你可以创建预制体的多个实例,然后重新编排各自的板条箱实体,以创造出你需要的效果。

保持相对位置 忽略相对位置
复制的箱子 随机摆放的箱子

断开与预制体的链接

添加预制体实例后,你可以断开预制体与其任何子级实体之间的链接。这意味着该子级实体不再受你对预制体所做更改的影响。

具体操作:在场景编辑器中,右键单击一个或多个子级实体并选择断开与预制体的链接(Break link to prefab)。

断开子级与预制体之间的链接

在运行时实例化并添加预制体

要在运行时使用预制体,你需要先实例化它们,然后在代码中将它们添加到场景。

public class SpawnPrefabOnStart : StartupScript
{
    public Prefab MyPrefab { get; init; } // 这里使用 init 可防止其他脚本修改此属性
    
    public override void Start()
    {
        // 预制体可能包含多个实体
        var entities = MyPrefab.Instantiate();
        // 将它们添加到该实体所在的场景
        Entity.Scene.Entities.AddRange(entities);
    }
}
Note

仅调用 Instantiate() 不足以将预制体实例添加到场景。你还需要用 Add() 或 AddRange() 将它们添加到场景中。例如,如果你的预制体包含一个模型,在添加预制体实例之前该模型是不可见的。同样,如果你的预制体包含一个脚本,在添加预制体实例之前该脚本不会工作。

如果你的项目根文件夹中有一个名为 MyBulletPrefab 的预制体,可以使用以下代码实例化并添加它:

private void InstantiateBulletPrefab()
{
    // 注意,"MyBulletPrefab" 指的是预制体资产的名称和位置
    var myBulletPrefab = Content.Load<Prefab>("MyBulletPrefab");

    // 实例化预制体
    var instance = myBulletPrefab.Instantiate();
    var bullet = instance[0];

    // 修改 X 坐标
    bullet.Transform.Position.X = 20.0f;

    // 只把这颗子弹添加到根场景
    SceneSystem.SceneInstance.RootScene.Entities.Add(bullet);
}
Note

在运行时,对预制体(上例中的 myBulletPrefab)所做的更改不会影响现有的预制体实例(上例中的 bullet)。之后调用 Instantiate(Prefab) 会包含新的更改。 例如,假设你有一个树的预制体,其中包含一个脚本,可在运行时将树的颜色由绿变红。该脚本不会影响预制体的现有实例;它只能改变以后创建的实例的颜色。这意味着在代码运行之后实例化的预制体会拥有新颜色,而已有的预制体则不会。

另请参阅