Need help to understand Unity's logic or C# ?

Hello,

I try to make this work but I still got problems to initailize everything and accessing it correctly.

I have a game manager with a unique Awake() function for the moment. (singleton)

using UnityEngine;
using System.Collections;
using PoolSystem;

public class Master_GameManager : MonoBehaviour {

	// For the singleton pattern
	public static Master_GameManager gameManager;

	public ObjectPoolingManager poolManager;

	public Master_PlayerDataManager playerDataManager;

	// Use this for initialization (singleton pattern)
	public void Awake() {
		if (gameManager == null) {
			gameManager = this;
			DontDestroyOnLoad(gameObject);
		} else {
			Destroy(gameObject);
		}

		poolManager = new ObjectPoolingManager();

		playerDataManager = new Master_PlayerDataManager();
		playerDataManager.Initialization();
	}
}

I hope you see what I trying to do.

I have troubles when using Master_GameManager.gameManager.poolManager for example.

I’m getting mad, please save my mind :slight_smile:

Lionel

Ok so breakdown all this mess :smiley:

Master_GameManager.cs :

using UnityEngine;
using System.Collections;
using PoolSystem;

public class Master_GameManager : MonoBehaviour {

	// For the singleton pattern
	public static Master_GameManager gameManager;

	public ObjectPoolingManager poolManager;

	// To access others masters
	public Master_PlayerDataManager playerDataManager;

	// Properties

	// Events

	// Use this for initialization (singleton pattern)
	public void Awake() {
		if (gameManager == null) {
			gameManager = this;
			DontDestroyOnLoad(gameObject);
		} else {
			Destroy(gameObject);
		}

		// Init Managers /!\ Order is important /!\
		poolManager = new ObjectPoolingManager();
		// Create Fx, etc.. Pools. 

		playerDataManager = new Master_PlayerDataManager();
		playerDataManager.Initialization();

	}
}

This is the starting point of my application the only Awake() call. This monobehaviour is attached to a game object in my scene. It need to be the center for all my others manager that are not monobehaviours. Let’s take a look at these.

Master_PlayerDataManager.cs :

using UnityEngine;
using System.Collections;
using System.Runtime.Serialization.Formatters.Binary;
using System.IO;
using Ability_System;
using PoolSystem;

public class Master_PlayerDataManager {

	/*
	 * This class is sort of a base for every other "same" kind of class.
	 * TODO:
	 * 	- Change path system: Create string variable instead. √
	 */

	// Used for serialization and de-serialization and containing player datas.
	// Should be accessible from the outside
	public Data_Player dataPlayer = new Data_Player();

	// Player Spells
	[HideInInspector] public Ability_Spell playerMainSpell;
	[HideInInspector] public Ability_Spell playerSecondarySpell;

	private ObjectPoolingManager poolManager;

	// Private Vars
	string dataFilePath;

	// Constructor
	public void Initialization() {
		dataFilePath = Application.persistentDataPath + "/Data_player.dat";
		poolManager = Master_GameManager.gameManager.poolManager;

		if (!PlayerDataLoad()) {
			InitDefaultPlayerData();
		}

		ChangePlayerMainSpell(dataPlayer.mainSpell);
		ChangePlayerSecondarySpell(dataPlayer.secondarySpell);
	}

	public void InitDefaultPlayerData() {
		dataPlayer.maxHealth = 100;
		dataPlayer.health = 100;
		dataPlayer.maxMana = 200;
		dataPlayer.mana = 200;
		dataPlayer.speed = 1f;
		dataPlayer.mainSpell = "Fireball";
		dataPlayer.secondarySpell = "Firenova";
	}

	public void ChangePlayerMainSpell(string newSpellName) {
		playerMainSpell = (Ability_Spell)Resources.Load("Abilities/" + newSpellName);
		poolManager.CreatePool(playerMainSpell.prefab, 20, 50, true); // Create new ability pool
		poolManager.DeletePool(dataPlayer.mainSpell); // Try to delete old ability pool
		dataPlayer.mainSpell = newSpellName;
	}

	public void ChangePlayerSecondarySpell(string newSpellName) {
		playerSecondarySpell = (Ability_Spell)Resources.Load("Abilities/" + newSpellName);
		//poolManager.CreatePool(playerSecondarySpell.prefab, 20, 50, true); // Create new ability pool
		//poolManager.DeletePool(dataPlayer.secondarySpell); // Try to delete old ability pool
		dataPlayer.secondarySpell = newSpellName;
	}

	public bool PlayerDataLoad() {
		if (File.Exists(dataFilePath)) {
			BinaryFormatter bf = new BinaryFormatter();
			FileStream file = File.Open(dataFilePath, FileMode.Open);
			dataPlayer = (Data_Player)bf.Deserialize(file);
			file.Close();
			return true;
		}
		return false;
	}

	public void PlayerDataSave() {
		BinaryFormatter bf = new BinaryFormatter();
		FileStream file = File.Create(dataFilePath);
		bf.Serialize(file, dataPlayer);
		file.Close();
	}

}

a more complex script indeed. So no need of building an empty constructor because it won’t do nothing. I have the Initialization() function that will … initialize :open_mouth:

as I said I create my pools here. (one for each Spell of the player) In this script there is no error thrown by the compiler :smiley: Just to show you :wink:

So let’s take my spell caster script.

using UnityEngine;
using System.Collections;
using Ability_System;
using PoolSystem;

public class Player_SpellCaster : MonoBehaviour {

	// ref
	Master_PlayerDataManager playerDataManager;
	Data_Player playerData;
	ObjectPoolingManager poolManager;

	// vars
	Ability_Spell mainSpell;
	Ability_Spell secondarySpell;

	GameObject instance;

	float mainSpellNextFire;
	float secondarySpellNextFire;
	float time;

	// init
	void Start() {
		playerDataManager = Master_GameManager.gameManager.playerDataManager;
		playerData = playerDataManager.dataPlayer;
		mainSpell = playerDataManager.playerMainSpell;
		secondarySpell = playerDataManager.playerSecondarySpell;

		poolManager = Master_GameManager.gameManager.poolManager;
	}
	
	// Update is called once per frame
	void Update() {
		// update refs if needed.
		if (mainSpell.name != playerData.mainSpell) {
			// Update ref
			mainSpell = playerDataManager.playerMainSpell;
		}
		if (secondarySpell.name != playerData.secondarySpell) {
			// Update ref
			secondarySpell = playerDataManager.playerSecondarySpell;
		}

		time = Time.time;

		if ((Input.GetMouseButton(0)) && (time > mainSpellNextFire)) { // Left click
			mainSpellNextFire = Time.time + mainSpell.cooldown;
			CastSpell(mainSpell);
		} else if ((Input.GetMouseButton(1)) && (time > secondarySpellNextFire)) { // Right click
			secondarySpellNextFire = Time.time + secondarySpell.cooldown;
			CastSpell(secondarySpell);
		}
	}

	void CastSpell(Ability_Spell spellToCast) {
		/*
		 * TODO:
		 * 	- 
		 */
	
		switch (spellToCast.type) {
			case Ability_Types.PROJECTILE:
				// Cast Projectile code
				Vector2 target = Camera.main.ScreenToWorldPoint(new Vector2(Input.mousePosition.x, Input.mousePosition.y));
				Vector2 myPos = new Vector2(transform.position.x, transform.position.y);
				Vector2 direction = target - myPos;
				direction.Normalize();
				Quaternion rotation = Quaternion.Euler(0, 0, Mathf.Atan2(direction.y, direction.x) * Mathf.Rad2Deg - 90);
				instance = poolManager.GetObject(spellToCast.abilityName);
				instance.transform.position = myPos;
				instance.transform.rotation = rotation;
				instance.GetComponent<Rigidbody2D>().velocity = direction * spellToCast.speed;
				instance.SetActive(true);
				break;
			case Ability_Types.NOVA:
				// Cast Nova code
				break;
			default:
				break;
		}

		Debug.Log("Spell Casted Name :" + spellToCast.name);
	}
}

Here everything start to get funny. When I set up my references here my poolManager have no pool in it. And when I trace I know that I create one. So let’s take a loot at the poolingManager.

using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using System;

namespace PoolSystem {

	public class ObjectPoolingManager {

		//look up list of various object pools.
		private Dictionary<String, ObjectPool> objectPools;

		public ObjectPoolingManager() {
			//Ensure object pools exists.
			objectPools = new Dictionary<String, ObjectPool>();
		}

		public bool CreatePool(GameObject objToPool, int initialPoolSize, int maxPoolSize, bool shouldShrink) {
			//Check to see if the pool already exists.
			if (objectPools.ContainsKey(objToPool.name)) {
				//let the caller know it already exists, just use the pool out there.
				return false;
			} else {
				//create a new pool using the properties
				ObjectPool nPool = new ObjectPool(objToPool, initialPoolSize, maxPoolSize, shouldShrink);
				//Add the pool to the dictionary of pools to manage
				//using the object name as the key and the pool as the value.
				objectPools.Add(objToPool.name, nPool);
				//We created a new pool!
				return true;
			}
		}

		public bool DeletePool(string name) {
			if (objectPools.ContainsKey(name)) {
				objectPools.Remove(name);
				return true;
			} 
			return false;
		}

		public GameObject GetObject(string objName) {
			//Find the right pool and ask it for an object.
			return objectPools[objName].GetObject();
		}
	}
}

When I get the instance from my gameManager the private Dictionary objectPools is empty (count=0) but when I trace the creation of the pool for my player mainspell objectPools have count=1…

Is the problem here ? because the dictionary is private ? That make no sens to me. If somebody could find where I’m false, this will help a lot :slight_smile:

Thanks everybody :smiley: