0
votes

I'm creating a procedural generated game, which will generate new "terrain" forever, do to this my game starts to lag, so I'm trying to unload some chunks, which I'd later like to load again (if the player comes back to that specific position again)...

This is my code for unloading:

GameObject _tmp = MapGeneration.Map[Mathf.Abs(y)][x];
DestroyImmediate(MapGeneration.Map[Mathf.Abs(y)][x].gameObject);
MapGeneration.Map[Mathf.Abs(y)][x] = _tmp;

Later when I try to instantiate the block again:

Instantiate(MapGeneration.Map[Mathf.Abs(y)][x].gameObject, new Vector3(x, y, 0), Quaternion.identity);

I get this error:

MissingReferenceException: The object of type 'GameObject' has been destroyed but you are still trying to access it. Your script should either check if it is null or you should not destroy the object. UnityEngine.Object.Internal_InstantiateSingle (UnityEngine.Object data, Vector3 pos, Quaternion rot) UnityEngine.Object.Instantiate (UnityEngine.Object original, Vector3 position, Quaternion rotation) MapGeneration.Update () (at Assets/Scripts/MapGeneration.cs:53)

2
Wait.. What? You know C# is pass by reference yes? So if you pass an instance of an object to a variable and then destroy that instance, the variable is also going to point to nothing? Hence your errorUser1
Yea, I know, which is why I've come to you guys to seek advice.Mobilpadde

2 Answers

4
votes

You don't want to destroy the object, you want to disable it so that it doesn't take up processing resources. Using Destroy() means the object is gone, completely gone.

Have a look at SetActive().

http://docs.unity3d.com/ScriptReference/GameObject.SetActive.html

It's essentially the code equivalent of the little tick box top left of the object/components in the inspector panel. Whilst inactive the engine will "skip" it, but this also includes functions like Find() and GetComponent(), so make sure you have a stored reference to the gameobject before you set it to inactive or you'll not be able to "discover" it again.

0
votes

you cannot access any gameObject after you destroy it.

To solve this, you have to create prefabs for your objects, the following steps show how to create and destroy one object using prefabs:

1- Create a prefab for one of your objects. (e.g. "terrain1" object) 2- In your script (class level), define the following variables as follows:

public GameObject terrain1Prefab;
GameObject terrain1Instance;

3- Link the public variable "terrain1Prefab" to your created prefab.

4- In your function, create an instance of "terrain1Prefab" and store its instance as follows:

terrain1Instance = Instantiate(terrain1Prefab, new Vector3(x, y, 0), Quaternion.identity);

5- Now, you can destroy your instance as follows:

Destroy(terrain1Instance);