i use two classes to instantiate gameobject and recycle them , but when i reload the scene or go to another scene and come back to this scene there is error :
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
public class GameObjectUtil {
private static Dictionary<RecycleGameObject, ObjectPool> pools = new Dictionary<RecycleGameObject, ObjectPool> ();
public static GameObject Instantiate(GameObject prefab, Vector3 pos){
GameObject instance = null;
var recycledScript = prefab.GetComponent<RecycleGameObject> ();
if (recycledScript != null) {
var pool = GetObjectPool (recycledScript);
instance = pool.NextObject (pos).gameObject;
} else {
instance = GameObject.Instantiate (prefab);
instance.transform.position = pos;
}
return instance;
}
public static void Destroy(GameObject gameObject)
{
var recyleGameObject = gameObject.GetComponent<RecycleGameObject> ();
if (recyleGameObject != null)
{
recyleGameObject.Shutdown ();
}
else
{
GameObject.Destroy (gameObject);
}
}
private static ObjectPool GetObjectPool(RecycleGameObject reference){
ObjectPool pool = null;
if (pools.ContainsKey (reference)) {
pool = pools [reference];
} else {
var poolContainer = new GameObject(reference.gameObject.name + "ObjectPool");
pool = poolContainer.AddComponent<ObjectPool>();
pool.prefab = reference;
pools.Add (reference, pool);
}
return pool;
}
}
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;
Debug.Log (go);
}
}
if(instance == null)
instance = CreateInstance (pos);
instance.Restart ();
return instance;
}
}
the error is like :
MissingReferenceException: The object of type 'RecycleGameObject' 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.NextObject (Vector3 pos) (at Assets/Scripts/ObjectPool.cs:26)
GameObjectUtil.Instantiate (UnityEngine.GameObject prefab, Vector3 pos) (at Assets/Scripts/GameObjectUtil.cs:15)
Spawner+<EnemyGenerator>c__Iterator1.MoveNext () (at Assets/Scripts/Spawner.cs:24)
UnityEngine.SetupCoroutine.InvokeMoveNext (IEnumerator enumerator, IntPtr returnValueAddress) (at C:/buildslave/unity/build/Runtime/Export/Coroutines.cs:17)
i dont know ho to make it go away . i debug log and here is main part of code problem :
foreach (var go in poolInstances) {
if(go.gameObject.activeSelf != true){
instance = go;
instance.transform.position = pos;
Debug.Log (go);
}
}
It would appear that your RecycleGameObject instances aren’t surviving the scene loads but your poolInstances list is still holding onto references to them. Either clear the list when changing scenes or check if go is null before checking activeSelf.
Static members aren’t cleared between scenes. You need to set your “pools” Dictionary to null. When you’re using static members or delegates, you need to be aware of lifecycle management.
i actually used a video tutorial series to be there , would you please my friends , changing required steps in above codes and i use them , because i am not too much professional with dictionary and list and what you advised me . it would be great while its 3 weeks that in this step i have no clue to continue my learning - while doing projects . thanks . i also try to do what you both told me here .
Since we learned yesterday that Dameon doesn’t actually write code or provide full explanations to help people without being paid, I’ll explain what he meant (and what I alluded to) a bit further.
Your dictionary is static - which means it lives “at the class level”. It also means that when you load a new scene all of the values in that dictionary remain where they are but the actual objects being referenced in the dictionary no longer exist (because the scene load destroyed them). That’s what the error is telling you when it says you’re trying to reference an object that was destroyed.
The most straightforward way to get rid of this error is to “reset” your dictionary when you load a new scene. You can do that by adding a new method to your GameObjectUtil class
public static void Reset()
{
pools.Clear();
}
and then call that Reset method in the same spot you’re doing your scene changes.
KelsoMRK thanks , you are a very good teacher , it helped me to make that error go away , i now have a complete different question while this current problem is gone away by your recommendations. i use below code to come from main menu scene to gameplay scene :
using UnityEngine;
using System.Collections;
using UnityEngine.UI;
using UnityEngine.SceneManagement;
public class MainmenuManager : MonoBehaviour {
public Canvas Mainmenu;
public GameObject SettingsPanel;
public GameObject CreditsPanel;
public GameObject BuycoinsPanel;
public GameObject IngameplaypausePanel;
public PlayerMovement pm;
public Scrollbar yourScrollbar;
void Start ()
{
Mainmenu = Mainmenu.GetComponent<Canvas> ();
}
public void PlayGame()
{
SceneManager.LoadScene (2);
}
during gameplay whenever i use this code , its ok . but when and when gameover codes run , and i go to main menu scene and come back in that situation to gameplay scene , spawner and background acrolling dont work , only player movement code runs .
here are my classes :
using UnityEngine;
using System.Collections;
using UnityEngine.UI;
using UnityEngine.SceneManagement;
public class GameController : MonoBehaviour
{
public GameObject GameoverPanel;
public GameObject Buttons;
public PlayerMovement pm;
public bool notcrashed = true;
public Animator anim;
public GameObject InGamepausePanel;
public GameObject PlayerPrefab;
private GameObject player;
void Awake()
{
anim = GameObject.Find ("Player").GetComponent<Animator> ();
}
void Start()
{
}
public void OnGameReset()
{
GameoverPanel.SetActive (false);
Buttons.SetActive (true);
SceneManager.LoadScene (2);
GameObjectUtil.Reset ();
Time.timeScale = 1;
InGamepausePanel.SetActive (false);
}
public void Restart()
{
StartCoroutine (retro ());
}
IEnumerator retro()
{
Buttons.SetActive (false);
pm.isPaused = false;
notcrashed = false;
var running = false;
anim.SetBool ("Running", running);
yield return new WaitForSeconds(2f);
Time.timeScale = 0;
gameoverPanel ();
}
public void gameoverPanel()
{
GameoverPanel.SetActive (true);
}
}
if you need more code , i would be happy to hear from you . thanks in any case.good luck .
P.S : Daemon , thanks for your helps too .
“doesn’t work” is rarely a sufficient explanation of the problem
You’ve got a lot going on and a ton of moving parts. It seems like you’ve at least narrowed the problem down to a set of discreet, recreate-able steps which is a fantastic start. Check the console for error messages and also pause the game and look at the objects in the scene to make sure that everything that’s in the scene when it works is also present in the scene when it doesn’t. Beyond that it’s going to be tough to provide any concrete advise.
Ok, when game play scene runs , and i go to main menu scene , and come back again to game play scene , its ok . but i understood only when player is collided with enemy and game over animation is run via a coroutine . now if i choose not to continue to play , and i go to main menu and in this case choose again to go to gameplay scene , here though there is no response from spawner and background scrolling .
In this case if i choose pause game play scene with ui button pause and retry gameplay scene from retry ui button , its ok .game play scene runs good . but only that visit of main menu after player game over is the problem .
how i can from one spawner instantiate prefab in different Y axis points?for example i need to instantiate in below positions :
1.2
1,3
1,4
1 is always X axis and 2,3,4 are Y axis different points .