非实例化加载预制件与实例化预制件相比如何?

How do non-instantiated loaded Prefabs compare to instantiated ones?

例子

在 Unity5 中,假设名称为“SomeObject”的游戏对象作为预制件存储在 Assets/Resources/SomeObject.prefab,我知道我可以按如下方式创建预制件的实例:

GameObject prefab   = Resources.Load<GameObject>("SomeObject");
GameObject instance = GameObject.Instantiate(prefab);

执行后,instance GameObject 将成为原始“SomeObject”预制件的副本,并将以名称“SomeObject(Clone)”放置在当前活动场景中。


据我了解,GameObject prefab代表实际的预制资产,对其所做的任何更改(设置名称、添加组件等)都会写入原始预制资产,并且这些更改会持续存在即使退出编辑器播放模式。

问题

  1. 由于所有GameObjects通常都存储在一个场景中,而上例中GameObject prefab上的scene 属性似乎是Unloaded/Invalid/Unnamed ,我到底应该在哪里考虑这个特殊的游戏对象?我似乎能够用它做我能用普通游戏对象做的所有事情,只是在 hierarchy/scene 视图中不可见。

    它实际上处于某种边缘状态,还是一种特殊的 PseudoScene?它似乎通过 LoadSceneMode.Single 场景变化持续存在,但不像传递到 GameObject.DontDestroyOnLoad(...).

    时对象移动到的特殊 DontDestroyOnLoad 场景
  2. 在上面的例子中,prefabinstance 之间是否还有其他值得注意的区别,除了生命周期变化、无效场景和彼此不同的对象(具有不同 GetInstanceID(),等等)?

  3. 由于在 prefab 上调用 GameObject.Instantiate(...) 会产生一个 在有效场景中的游戏对象,有没有办法手动创建处于类似 'no scene' 状态的游戏对象?我知道 Unity 打算让所有游戏对象都出现在场景中,所以这纯粹是一个学术问题。

我已经尝试查看 documentation of the functions involved,但是 none 深入了解了当您在预制资源上调用 Resources.Load 时具体发生了什么的技术细节。

1.Where exactly should I consider this special GameObject to be?

它位于单独的文件中,未在场景中引用。一旦Resources.Load<GameObject>("SomeObject");被调用,它被加载到内存中,等待GameObject.Instantiate被调用时使用。

如果声明为 public GameObject prefab; 并从编辑器而不是 GameObject prefab Resources.Load<GameObject>("SomeObject"); 分配,它将在场景加载时自动加载到内存中。

2.Are there any other noteworthy differences between prefab and object?

是的。

无法使用DestroyDestroyObject函数销毁预制件。它必须通过将 true 传递给它的第二个参数来用 DestroyImmediate 函数销毁:DestroyImmediate(prefab, true);

3.Is there any way to manually create GameObjects that are in a similar 'no scene' state?

不,无法手动创建处于类似 'no scene' 状态的游戏对象。

虽然你可以伪造它。

最接近的是通过修改游戏对象的 hideFlags 变量然后停用该 GameObject。

GameObject obj = new GameObject("SomeObject");
obj.hideFlags = HideFlags.HideInHierarchy | HideFlags.HideInInspector;

之后,停用游戏对象:

obj.SetActive(false);

现在,GameObject 在编辑器中不可见,在场景和游戏视图中也不可见。


预制件和典型的游戏对象之间确实没有太大区别。 Prefab 只是一个容纳 GameObject 的容器,以便它可以在场景之间重复使用和共享。修改一个预制件将更新它的任何实例。

想象一下,当场景中有数百个相同类型的游戏对象并且需要修改所有这些对象时。使用预制件,您只需要修改其中一个或只修改预制件,然后单击应用以更新其他实例。这是您唯一应该想到的预制件。