【问题标题】:Move/Carry non root GameObject to another Scene移动/携带非根游戏对象到另一个场景
【发布时间】:2017-12-20 16:28:28
【问题描述】:

我在将两个游戏对象实例化到一个场景中时遇到了问题,该场景存储在前一个场景的两个变量中。我正在调试以确保变量确实填充了必要的游戏对象,它们确实如此。但是当我尝试将这些 Gameobject 实例化到新场景中时,我得到了错误:

ArgumentException: The Object you want to instantiate is null.
UnityEngine.Object.CheckNullArgument (System.Object arg, System.String message) (at C:/buildslave/unity/build/Runtime/Export/UnityEngineObject.cs:238)
UnityEngine.Object.Instantiate (UnityEngine.Object original, Vector3 position, Quaternion rotation) (at C:/buildslave/unity/build/Runtime/Export/UnityEngineObject.cs:150)
UnityEngine.Object.Instantiate[GameObject] (UnityEngine.GameObject original, Vector3 position, Quaternion rotation) (at C:/buildslave/unity/build/Runtime/Export/UnityEngineObject.cs:205)
GameManager.LoadAnimalAvatar () (at Assets/_Coloring_Book/__Scripts/GameManager.cs:84)
AvatarFinalPreview.Start () (at Assets/_Coloring_Book/__Scripts/ColoringBook/AvatarFinalPreview.cs:9)

我通过在调用 StoreAnimalAvatar 的第一个场景中单击按钮,将游戏对象分配给一个对象中的变量,该对象在场景之间持续存在(不要破坏),然后当我切换到下一个场景时,我有一个脚本( AvatarFinalPreview.cs) 在其 Start 函数中调用 LoadAnimalAvatar。我不确定为什么在我的调试日志中显示对象存在时它说对象为空。我做错了什么?

public void StoreAnimalAvatar()
    {
        GameObject uiObject3D = GameObject.Find("UIObject3D");
        GameObject animalToStore = GameObject.FindGameObjectWithTag("Avatar Preview");

        AnimalUIObject3D = uiObject3D;
        AnimalAvatar = animalToStore;

        Debug.Log("Animal Stored");
        Debug.Log(AnimalUIObject3D.name);
        Debug.Log(AnimalAvatar.name);
    }

    public void LoadAnimalAvatar()
    {
        GameObject canvas = GameObject.FindGameObjectWithTag("Canvas");

        GameObject uiObject3D = Instantiate(AnimalUIObject3D, new Vector3(0, 0, 0), Quaternion.identity) as GameObject;
        GameObject avatar = Instantiate(AnimalAvatar, new Vector3(0, 0, 0), Quaternion.identity) as GameObject;
        avatar.transform.SetParent(canvas.transform);
    }

【问题讨论】:

  • 这个问题已经被问过很多次了。 DontDestroyOnLoad(yourObject)...
  • 我有一个不在根目录中的游戏对象。当我尝试使用 DontDestryOnLoad 时,我收到错误 DontDestroyOnLoad only work for root GameObjects or components on root GameObjects. 是否有其他方法可以使用您的建议?
  • 尝试使用预制件。
  • @Draco18s 我存储的游戏对象具有在运行时应用的自定义纹理。
  • 哦,在那种情况下。停止使用场景。

标签: c# unity3d instantiation


【解决方案1】:

当我尝试使用 DontDestryOnLoad 时出现错误 DontDestroyOnLoad 仅适用于根 GameObjects 或根上的组件 游戏对象。是否有其他方法可以使用您的建议?

您有三个选择:

1。将该子对象的父对象设置为 null,然后对其调用 DontDestroyOnLoad。这将使该对象不再有父对象,以便 DontDestroyOnLoad 对其进行处理:

public GameObject yourChildObj;

....

yourChildObj.transform.parent = null;
DontDestroyOnLoad(yourChildObj);

2.在该对象的根上调用DontDestroyOnLoad。请注意,这将使根对象及其子对象存活。之后您必须手动销毁其他子对象和父对象,因为您只需要该子对象。

获取该子对象的根对象。获取该根对象下除该子对象之外的所有子对象并将它们存储在一个数组中。将该子对象的父对象设置为 null,然后对该子对象调用 DontDestroyOnLoad。现在,销毁存储的子级和父级。

public GameObject yourChildObj;
...
Transform root = yourChildObj.transform.root;
ClearChildren(root, yourChildObj.transform);

ClearChildren 函数:

public void ClearChildren(Transform targetRoot, Transform exclude)
{
    Debug.Log(targetRoot.childCount);
    int i = 0;

    //Array to hold all child obj
    GameObject[] allChildren = new GameObject[targetRoot.childCount];

    //Find all child obj and store to that array
    foreach (Transform child in targetRoot)
    {
        if (child != exclude)
        {
            allChildren[i] = child.gameObject;
            i += 1;
        }
    }

    //Remove exclude as the child
    exclude.parent = null;
    DontDestroyOnLoad(exclude);

    //Now destroy them
    foreach (GameObject child in allChildren)
    {
        if (child != null)
            DestroyImmediate(child.gameObject);
    }

    //Now destroy the parent
    if (targetRoot != null)
        DestroyImmediate(targetRoot);
}

3。使用SceneManager.GetSceneByName 将该对象移动到另一个已加载的场景。

Scene yourNexScene = SceneManager.GetSceneByName("SceneName");
SceneManager.MoveGameObjectToScene(yourChildObj, yourNexScene);

我更喜欢 选项 1,但如果您需要在同一个根目录中有更多对象离开,那么 选项 2 让您有机会这样做。

【讨论】:

  • 感谢您提供此信息。因此,如果我使用选项 1 并将父级设置为 null,那么一旦我进入下一个场景,我就可以将游戏对象父级重新分配回画布,对吗?
  • 是的,您只需在其他场景中将其设为画布的子节点,它应该可以正常工作。我提到的第三个选项不需要使用DontDestroyOnLoad,但#1 应该没问题
  • 我将尝试所有三个选项,非常感谢您提供的宝贵意见。
  • Np。如果您遇到相关问题,您可以随时发表评论
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-10-18
  • 1970-01-01
相关资源
最近更新 更多