Home > other >  member variable only maintains assigned value for the scope of a function
member variable only maintains assigned value for the scope of a function

Time:10-08

I've got a dictionary of values Dictionary<string, ScreenState> _states and a string holding the current ScreenState:

struct ScreenState
    {
        public string name;
        public GameObject state;
        private Dictionary<string, ScreenState> _childStates;
        private string _currentChild;

        public ScreenState(GameObject fab)
        {
            name = fab.name;
            state = Instantiate(fab) as GameObject;
            state.transform.position = new Vector3(100, 100, 100);

            _childStates = new Dictionary<string, ScreenState>();
            GameObject[] children = fab.GetComponent<ChildStates>().childFABs;
            for (int ch = 0; ch < children.Length; ch  )
                _childStates.Add(children[ch].name, new ScreenState(children[ch]));

            if (_childStates.Count > 0)
                _currentChild = _childStates.ElementAt(0).Key;
            else
                _currentChild = null;
        }

        public void EnableState()
        {
            state.transform.position = new Vector3(-5, 2, -20);
            if (_currentChild != null)
                _childStates[_currentChild].EnableState();
        }

        public void DisableState()
        {
            state.transform.position = new Vector3(100, 100, 100);
            if (_currentChild != null)
                _childStates[_currentChild].DisableState();
        }

        public void ChangeChildState(string stt)
        {
            _childStates[_currentChild].DisableState();
            _childStates[stt].EnableState();
            _currentChild = stt;
        }
    }

The ScreenStates also have children ScreenStates that are stored in Dictionary<string, ScreenState> _childStates, which are changed with ChangeChildState, through _states[_currentState].ChangeChildState("foo");. It works almost exactly as I want it to. The player can go into the "Bazar" state, which holds "BazarBuyBug" and "BazarBuyFurniture". When the Bazar state is started, it defaults to the BazarBuyBug state. When the player changes child state, the currently enabled child state is disabled, the new one is enabled, and the new current child state is stored in _currentChild.

It switches between them correctly, but after setting a bunch of Debug checks to track the value of _currentChild throughout the code, it looks like when ChangeChildState is called, the value of _currentChild is only changed for the scope of the function, and stays as "BazarBuyBug" forever. Therefor, when the state is supposed to change off of BazarBuyFurniture, the child state is never disabled... This is driving me up a wall.

CodePudding user response:

The problem you're seeing is because you're using struct as your ScreenState, which is a "value type".

Your line _states[_currentState].ChangeChildState("foo"); when borken down first gets the _states[_currentState] struct, which is a value type and not a referenced object to struct in the dictionary. In other words, it's a new struct. So, when you then call ChangeChildState("foo"), you're working on the new object, not the one stored in the dictionary.

The simplest solution would be to change ScreenState to a class. Some people would argue that because you've got "reference types" in ScreenState, you should be making this a class anyway.

If you would prefer to, or need to, keep ScreenState as a struct, you could modify your code to this:

var ss = _states[_currentState];
ss.ChangeChildState("foo");
_states[_currentState] = ss;
  • Related