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 :)
Lionel
What means "I have troubles"? Do you have error messages? When do you have troubles? What are you trying to call and where? What does the code on the other side look like?
Your... Technically calling the same script... In the same script when you use $$anonymous$$aser_Game$$anonymous$$anger (your now in the script).game$$anonymous$$anager(your now in the script... Again).pool$$anonymous$$anager -- I dont think the whole processs is needed, you could shorten that to $$anonymous$$aster_Game$$anonymous$$anager.pool$$anonymous$$anager
2 possible other things may be happening... If pool$$anonymous$$anager does actually show up in IntelliSense, then, pool$$anonymous$$anager is set to a NEW value, but that value is still technically never set to anything, like setting a new array, but never filling the array, so it just returns nothing or could produce an error trying to do a calculation or access it (or something inside it)
Another possible thing that could be happening is ObjectPooling$$anonymous$$anager may not be set in your inspector, or straight up be private or never accessible
But there is certainly some more info needed from you, in terms of what your actual error your getting is, as InfiniBuzz mentioned.
@Dibble he has the right method for accessing his variable. To break it down the way you did...$$anonymous$$aster_Game$$anonymous$$anager(type).game$$anonymous$$anager(static instance).pool$$anonymous$$anager(non static variable). He could access pool$$anonymous$$anager the way you susgested if it was a static variable but not what he is trying to do.
Interetsing, "pool$$anonymous$$anager" is public, so I figured since its a script either way, it would be just as accessible the other way, but the technical breakdown helps - without an IDE infront of me, its hard to sometimes identify things - the colorcode helps haha, but thank you for clearing that up
Hello,
So I need to give a little more details.
@InfiniBuzz: This is a long story but the first big problem is accessing my public objects from my game manager. For example I have to access the pooler manager from a method that fires projectile (so I need to pool them). I want to be able to do : $$anonymous$$aster_Game$$anonymous$$anager.game$$anonymous$$anager.pool$$anonymous$$anager and have the same instance of the pooler$$anonymous$$anager Everywhere in the game. Not working.
@Dibbie: The pool$$anonymous$$anager instance is created before the playerData$$anonymous$$anager, this is the work of the playerData$$anonymous$$anager to iniatialize 2 pools for the player's skills. But again it seems I can't share the same instance every where. I'm loosing my $$anonymous$$d :D.
@Adamcbrz: Thanks for explaining it :)
So, briefly what I want to do :
$$anonymous$$ake every public object instance shared accross the game with the usual way of accessing it. $$anonymous$$aster_Game$$anonymous$$anager.game$$anonymous$$anager.instance.
Thanks.
Lionel
What I mean are error messages, behavior etc. "Not working" is very general and makes it hard to guess the cause of your problems. However if you try to acces public $$anonymous$$embers of the data and pool managers, yout code looks ok. BUT: Note that if your poolmanager and playerdatamanager are $$anonymous$$onobehaviors
DO NOT instantiate them with new
! So are they $$anonymous$$onoBehaviors? If so you need to either create a prefab with a gameobject and the scripts attached, then use Instantiate() OR create a new gameobject and AddComponent() from code.
Not working because I cannot access them correctly. I get error message of null references everywhere in my code because of the fact that I can't share the same instance around my game.
Here the error message won't help.
The other scripts are no $$anonymous$$onobehaviour.
$$anonymous$$aster_Game$$anonymous$$anager.game$$anonymous$$anager.pool$$anonymous$$anager
should not be null, unless you try to access it from other scripts in the Awake()
method, it is possible that the instances have not been initialized yet. If thats not the case, the error must be either in one of the calling scripts or in the Pool$$anonymous$$anager/PlayerData$$anonymous$$anager itself. Are you trying to call methods or accessing properties?
Also, sorry if it sounds like a dumb question, but did you create a gameobject in the scene and attached the $$anonymous$$aster_Game$$anonymous$$anager? if not, it will not be initialized at all.
Well it seems there is something out side of just this script. This script doesn't seem to be the problem. $$anonymous$$ost likely it is an order of operations problem. If you have a null ref error there should be a stack trace in the details of the error. That should explain the path it took to get the null. If you can't figure the trace out paste it here and we will try to help.
Answer by Lionel_Leeser · Oct 20, 2016 at 03:29 PM
Ok so breakdown all this mess :D
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 :O
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 :D Just to show you ;)
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 :)
Thanks everybody :D
Are you deleting the pool after you create it?
$$anonymous$$aster_PlayerData$$anonymous$$anager.ChangePlayer$$anonymous$$ainSpell
pool$$anonymous$$anager.CreatePool(player$$anonymous$$ainSpell.prefab, 20, 50, true); // Create new ability pool
pool$$anonymous$$anager.DeletePool(dataPlayer.mainSpell); // Try to delete old ability pool
HAHAHAHA you found it !!!!!!!!
Ohhhhh my god ! Thank you !
I hate working alone for this kind of thing I always need more than 2 eyes !!!
Thanks you, and my $$anonymous$$d thank you too !
I'm so stupid...
Your answer
Follow this Question
Related Questions
Detecting Collision is not working 1 Answer
change sound pitch on object 0 Answers
Bullet Counter Not Working Propperly 0 Answers
How to make a GameObject dissapear when I'm close to them and click on them? 0 Answers
Why is my animation not working? 1 Answer