I'm having trouble instantiating two game objects into a scene that I've stored in two variables from a previous scene. I'm debugging to make sure that the variables are indeed populated with the necessary Gameobject, and they are. But when I try to instantiate these Gameobject into the new scene I'm getting the error:
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)
I'm assigning the gameobjects to variables in an object that persists from scene to scene (do not destroy) through a button click in the first scene that calls StoreAnimalAvatar and then when I switch to the next scene I have a script (AvatarFinalPreview.cs) that calls LoadAnimalAvatar in its Start function. I'm unsure why it's saying the object is null when in my debug log it shows that they exist. What am I doing incorrectly?
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);
}
When I've tried to use DontDestryOnLoad I get the error DontDestroyOnLoad only work for root GameObjects or components on root GameObjects. Is there another way to do this using your suggestion?
You have three options:
1.Set the parent of that child object to null then call DontDestroyOnLoad
on it. This will make the object not have a parent anymore so that DontDestroyOnLoad
will work on it:
public GameObject yourChildObj;
....
yourChildObj.transform.parent = null;
DontDestroyOnLoad(yourChildObj);
2.Call DontDestroyOnLoad
on the root of that object. Note that this will make the root object and its children live. You have to manually destroy other child objects and the parent after that since you only need that child object.
Get the root object of that child object. Get all the children under that root object except for that child object and store them in an array. Set the parent of that child object to null then call DontDestroyOnLoad
on that child object. Now, destroy the stored children and the parent.
public GameObject yourChildObj;
...
Transform root = yourChildObj.transform.root;
ClearChildren(root, yourChildObj.transform);
The ClearChildren
function:
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.Use SceneManager.GetSceneByName
to move that Object to another scene that has been loaded.
Scene yourNexScene = SceneManager.GetSceneByName("SceneName");
SceneManager.MoveGameObjectToScene(yourChildObj, yourNexScene);
I prefer option 1 but if you need more objects in the-same root to leave then option 2 gives you chance to do that.