
Error when trying to store a Monobehavior in a Dictionary
SOLUTION (u/Salt-Ad5394)
>You never initialize the dictionary! In Awake you're trying to check if _States.Empty but _States is null at this point
>Add `_States = new Dictionary<EEnemyState, EnemyScriptTemplate>();` at start of Awake before your loop. Also I think you mean `_States.Count == 0` instead of `_States.Empty` - dictionaries don't have Empty property
I've been working on an exam, and I wanted to create a script that serves as the body of a state machine, with the states themselves deriving from a template class.
I wanted to get all the components that derive from this template class, store them in a dictionary with an enum as a key, and enable/disable them to enter/exit them.
But I keep getting this error, despite the contents I'm trying to insert not being null. Is there something I am doing terribly wrong?
Here's the script:
public class EnemyStateMachine : MonoBehaviour
{
[field: SerializeField] public EnemyData EnemyData { protected get; set; }
//Ce dico contiendra tous les scripts d'états de la state machine,
//permettant la création d'un nouvel état par l'héritage avec EnemyScriptTemplate.
//Il suffit de le mettre sur l'ennemi, et de donner à l'état l'enum correct.
[field: SerializeField] private Dictionary<EEnemyState, EnemyScriptTemplate> _States { get; set; }
[field: SerializeField] private EEnemyState _SavedState { get; set; }
private void Awake()
{
//On cherche tous les scripts suivant le template d'état,
//et on vérifie si l'état qu'ils ont est déjà dans le dico.
//Si oui, on passe au suivant, sinon, on le rajoute avec son étant en guise de clé.
List<EnemyScriptTemplate> l_scriptList = new List<EnemyScriptTemplate>(GetComponentsInChildren<EnemyScriptTemplate>(true));
for (int l_increment = 0; l_increment < l_scriptList.Count; l_increment++)
{
if(l_scriptList[l_increment] != null) Debug.Log(l_scriptList[l_increment].State);
//!THE ERROR HAPPENS ON THE NEXT LINE!
if (_States.Empty || !_States.ContainsKey(l_scriptList[l_increment].State)) _States.Add(l_scriptList[l_increment].State, l_scriptList[l_increment]);
}
_SavedState = EEnemyState.NONE;
}
// Start is called once before the first execution of Update after the MonoBehaviour is created
void Start()
{
SetStateActive(true);
}
// Update is called once per frame
void Update()
{
if (EnemyData.State != _SavedState) NewState();
}
private void NewState()
{
SetStateActive(false);
_SavedState = EnemyData.State;
SetStateActive(true);
}
private void SetStateActive(bool p_newActive)
{
_States[_SavedState].enabled = p_newActive;
}
}