using UnityEngine;
using System.Collections;
using System.Collections.Generic;
public class ObjectPool : MonoBehaviour
{
public RecycleGameObject prefab;
private List<RecycleGameObject> poolInstances = new List<RecycleGameObject>();
private RecycleGameObject CreateInstance(Vector3 pos)
{
var clone = GameObject.Instantiate (prefab);
clone.transform.position = pos;
clone.transform.parent = transform;
poolInstances.Add (clone);
return clone;
}
public RecycleGameObject NextObject(Vector3 pos)
{
RecycleGameObject instance = null;
foreach (var go in poolInstances)
{
if(go.gameObject.activeSelf != true)
{
instance = go;
instance.transform.position = pos;
}
}
if (instance == null)
instance = CreateInstance (pos);
instance.Restart ();
return instance;
}
}
Hello, as soon as pool create a clone and i change the scene a to scene b , and i come back to the scene a
there is an exception error . how to fix this error? i tried many searching. but not useful.
That error occurs when a Unity object has been destroyed but you are still trying to use it.
In this case, it looks like you created some objects and stored them in your “poolInstances” list, then they all got destroyed when you changed scenes, but you didn’t clear your list, so you kept trying to use them even though they were gone.
You either need to prevent those objects from being destroyed when you change scenes OR stop using them when they get destroyed. Some possible ways to handle this include:
Check whether “go” is null before you do anything else with it, and if it’s null, remove it from your list. (NOTE: You shouldn’t remove something from a collection while you are iterating over it with a “foreach” loop, so this might require some careful restructuring)
When you change scenes, clear your entire list
Make the objects in your pool DontDestroyOnLoad
Allow the object pool itself to be destroyed when you change scenes, and create a new one in the new scene
I will thank you for your help. I like to use this offer:
Allow the object pool itself to be destroyed when you change scenes, and create a new one in the new scene
Could you please , step by step help me to implement this offer?
I am new to learning programming. But if you give me descriptions , i follow your tips to get the errors out of the console.
so , pool exist only in the scene a .
in the scene b there is no pool at all.
how to destroy the pool when going to scene b and when come back to scene a , create it again there?
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
public class ObjectPool : MonoBehaviour
{
public RecycleGameObject prefab;
private List<RecycleGameObject> poolInstances = new List<RecycleGameObject>();
private RecycleGameObject CreateInstance(Vector3 pos)
{
var clone = GameObject.Instantiate (prefab);
clone.transform.position = pos;
clone.transform.parent = transform;
poolInstances.Add (clone);
return clone;
}
public RecycleGameObject NextObject(Vector3 pos)
{
RecycleGameObject instance = null;
bool nullFound = false;
foreach (var go in poolInstances)
{
if (go == null)
{
nullFound = true;
}
if((go != null) && (go.gameObject.activeSelf != true))
{
instance = go;
instance.transform.position = pos;
}
}
if (instance == null)
instance = CreateInstance (pos);
instance.Restart ();
if (nullFound)
{
FlushNull();
}
return instance;
}
public void FlushNull()
{
foreach (RecycleGameObject go in poolInstances.toArray())
{
if (go == null)
{
poolInstances.Remove(go);
}
}
}
}
The above probably works. I didn’t test it, just wrote the changes into the forum.
What it does is check if the next object in the pool is not null first before trying to use it. That should avoid the error you are getting. If it is null, it sets a bool to true, where later after it is done setting up the pool object it will iterate through the poolInstances list and remove all null references (destroyed objects) by calling FlushNull(). You can optionally just call FlushNull() whenever you start a new scene so the first time you try to grab a pool object it doesn’t call FlushNull at that time.
The start of the scene is probably a better time performance wise to call it than when you’re trying to pull from the pool, but that isn’t required.
Edit: It is basically @Antistone 's first solution, leaving the option open to you to use his second suggested solution.
Thanks for your help , this time after changing the scene and coming back , there will be one clone instantiated and then it will show the following error in the console.
MissingReferenceException: The object of type 'ObjectPool' 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.
ObjectPool.CreateInstance (UnityEngine.Vector3 pos) (at Assets/Scripts/ObjectPool.cs:16)
ObjectPool.NextObject (UnityEngine.Vector3 pos) (at Assets/Scripts/ObjectPool.cs:42)
GameObjectUtil.Instantiate (UnityEngine.GameObject prefab, UnityEngine.Vector3 pos) (at Assets/Scripts/GameObjectUtil.cs:19)
Spawner+<EnemyGenerator>d__5.MoveNext () (at Assets/Scripts/Spawner.cs:27)
UnityEngine.SetupCoroutine.InvokeMoveNext (System.Collections.IEnumerator enumerator, System.IntPtr returnValueAddress) (at C:/buildslave/unity/build/Runtime/Export/Scripting/Coroutines.cs:17)
when double clicking on the error this line will be highlighted :
Well it looks like you’ve destroyed the ObjectPool component now, or the object it is attached to. The above help was with the assumption you weren’t doing that. If you’re going to destroy the old ObjectPool between scene loads, you’ll just have to create it again on scene load like how you created it on the first scene load. Otherwise, don’t destroy it.
I don’t understand. At some point in the game you’re already putting the ObjectPool into a scene, likely either as part of the scene itself, or by instantiating a prefab with it attached. To recreate it you would just do exactly the same thing you already did the first time you created it.
Otherwise, yes, using DontDestroyOnLoad on some script attached to the GameObject (including in Start in the ObjectPool script), will prevent it from getting automatically destroyed when switching scenes. Assuming the GameObject is at the root of the scene (not a child object).
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
public class ObjectPool : MonoBehaviour
{
public RecycleGameObject prefab;
private List<RecycleGameObject> poolInstances = new List<RecycleGameObject>();
void Awake()
{
DontDestroyOnLoad(this.gameObject);
}
private RecycleGameObject CreateInstance(Vector3 pos)
{
var clone = GameObject.Instantiate(prefab);
clone.transform.position = pos;
clone.transform.parent = transform;
poolInstances.Add(clone);
return clone;
}
public RecycleGameObject NextObject(Vector3 pos)
{
RecycleGameObject instance = null;
foreach (var go in poolInstances)
{
if (go.gameObject.activeSelf != true)
{
instance = go;
instance.transform.position = pos;
}
}
if (instance == null)
instance = CreateInstance(pos);
instance.Restart();
return instance;
}
}
I searched a lot and finally added
void Awake()
{
DontDestroyOnLoad(this.gameObject);
}
to this script . now the error does not show in the consile. However when i change between the scenes, the instantiated objects from the pool dont get reset .
when i go from scene a to the scene b , instantiated clones are in their position and keep their animation.
How would be possible to reset their movement and animations state to the initial position?
public class ObjectPool : MonoBehaviour
{
private static ObjectPool _instance;
public static ObjectPool Instance { get { return _instance; } }
public RecycleGameObject prefab;
private List<RecycleGameObject> poolInstances = new List<RecycleGameObject>();
void Update()
{
if (SceneManager.GetSceneByName("Level01").isLoaded)
{
if (_instance != null && _instance != this)
{
Destroy(this.gameObject);
}
else
{
_instance = this;
}
}
else if (SceneManager.GetSceneByName("Mainmenu").isLoaded)
{
Debug.Log("d");
Destroy(this.gameObject);
}
}
now in scene a it is ok , when i go to scene b its ok too.
when i come back to scene a its ok
but when for the second time i go to scene b it shows error :
MissingReferenceException: The object of type 'RecycleGameObject' has been destroyed but you are still trying to access it.