2017-06-15 116 views
3

实施例

在Unity5,假设名称为“SomeObject”一个游戏物体在Assets/Resources/SomeObject.prefab存储为一个预制的,我知道我可以如下创建该预制的一个实例:非实例化的加载的Prefab如何与实例化的比较?

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

一旦执行,游戏对象instance将是原始“SomeObject”预制件的副本,并将被放置在当前活动场景中,名称为“SomeObject(克隆)”。


据我了解,在GameObject prefab代表实际的预制资产,并把它(设置名称,添加成分等)写入到原来的预制资产,而这些变化坚持,即使之后所做的任何更改退出编辑器播放模式。

问题

  1. 由于所有GameObjects通常存储在一个场景,并在上面的例子中scene财产上GameObject prefab似乎被卸载/无效/未命名的,正是我应该考虑这个特殊的游戏对象,以是?我似乎能够用它做所有事情,我可以用普通的GameObjects完成任何事情,但在层次结构/场景视图中显示不出来。

    它有效地处于某种缓冲状态,还是一种特殊的PseudoScene?它似乎通过LoadSceneMode.Single场景变化持续存在,但并不像DontDestroyOnLoad场景那样当对象被传递到GameObject.DontDestroyOnLoad(...)时被移动到该场景。

  2. 是否有在上述的例子prefabinstance之间的任何其它值得注意的差异,比寿命的变化,无效场景其他并且是从一个不同的对象另一个(具有不同的GetInstanceID()等)?

  3. 由于呼吁prefabGameObject.Instantiate(...)产生一个游戏对象是是一个有效的场景,是有什么办法可以手动创建一个类似的“无现场”状态GameObjects?我知道Unity打算让所有GameObjects出现在场景中,所以这纯粹是一个学术问题。

我试图翻翻functionsinvolveddocumentation,但没有进入具体是什么正在发生的技术细节,当你对一个预制资源调用Resources.Load

+0

正如你大概可以告诉我有效地一次推出3个问题,我现在处于一个缺乏直觉的位置,以便真正知道我不知道的是什么,如果这是有道理的。再试一次:因为Resources.Load产生的GameObject处于无法手动创建的状态,所以我很好奇这些差异的确切性质,并希望有更多关于幕后操作的知识的人可以提供洞察力进入这里玩的系统,这些系统在正常文档中可能不会立即显现出来。我很抱歉无法更清楚地说出这一点。 – Johannes

回答

3

1.我到底该考虑这个特殊的GameObject吗?

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

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

2.预制件和对象之间是否还有其他值得注意的区别?

是的。

预制件不能用DestroyDestroyObject功能销毁。它必须通过传递true其第二arguement与DestroyImmediate功能被破坏:DestroyImmediate(prefab, true);

3.Is有什么办法可以手动创建一个类似的“无现场”状态GameObjects?

不,没有办法手动创建处于类似“无场景”状态的GameObjects。

虽然你可以伪造它。

最接近的事情就是通过修改GameObjects的hideFlags变量,然后停用游戏物体,使游戏对象的编辑层次督察标签不可见。

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

之后,停用游戏对象:

obj.SetActive(false); 

现在,游戏对象是在编辑器中不可见的,它也是在场景和游戏观无形。


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

想象一下,当您在场景中有数百个相同类型的GameObjects并需要修改所有这些类型时。使用预制,您只需修改其中一个或只是预制,然后单击应用即可更新其他实例。这是你应该考虑预制的唯一的事情。

+0

我也很好奇预制件gameObject和原始预制件之间的联系如何建立,以及它如何立即序列化。戳在https://github.com/MattRix/UnityDecompiled看起来'Resources.Load'最终导致extern函数,所以它在Unity的C++端的某个地方。一位朋友指出,预制可能是一个专门的C++对象,与一个GameObject .net接口一起生活。有什么想法吗? – Johannes

+1

我不得不通过'.Net反射器'来验证。它调用一个本地C++函数,该函数接受prefab的路径和prefab的预制类型:'public static extern Object Load(string path,Type systemTypeInstance);'。我认为C++端将用提供的路径加载文件,然后将该预制文件中的数据反序列化到内存中,然后将其作为“Object”返回。预制文件格式是专有的,除非你为Unity工作并且拥有C++源代码,否则很难猜测它的内部结构。 – Programmer

+0

只是对于第一次在这里学习'hideFlags'的人来说,它可能也值得追加'HideFlags.HideFlags.DontSave'或者只是使用'HideFlags.HideAndDontSave'来代替,因为有物体你看不到堆积可能是一个潜在的问题。 – Johannes