Accessing classes from UI state machine

This takes a lil’ explaining, I’ll try and be concise:

I’m building a state machine for my ingame UI which deals with the 4 states you can be in: PlayState, PausedState, ChatState and StatisticsState.

I have an Interface, IGameInterfaceState that all 4 state classes implement and a GameplayUserInterface class that links everything together.

Here’s the thing. Each State has a set of Displays (chat scrolling, score, health, etc) and Inputs (these deal with intractable UI elements) and so when the machine transitions it needs to turn off anything not needed, and then the newly activated state will turn on anything that it needs.

###Le Test
The test scene I’m building is simply aiming to display a reticle (in its own class) while in PlayState. I’ll add all the other displays once the architecture is built.
I have one UI_Manager object that GameplayUserInterface and DisplayReticle are on, this is where I’ll add DisplayChat, DisplayEvents, etc, etc.

###Da Questions
I have two, one simple and one perhaps not so much. I’ve added the relevant code snippets below, compacted somewhat for brevity:

  1. How should I access other classes from the state machine? I’m looking for an extensible way of doing this, as there’s always the route of piling Finds, but that would be a nightmare. I’m hoping to collect everything that any part of the state machine needs in the GameplayUserInterface or something to that effect…
  2. The (probably) harder question, how might I structure the state machine to deal with transitions easily? I’d like to be able to tweak them a bit, e.g. the UI fades out, fullscreen blur while the pause screen fades in. It seems like that kind of thing would be clunky with my current system?

Any advice, notes or references would be massively appreciated. And code snippets! I love a good code snippet… I never formally learnt C# or any programming language, so having actual examples of what someone’s talking about goes a really long way for me, as opposed to “Just put the polymorphic z-buffer in the dynamic function portlet” (It really can sound like that). Concepts are great, jargon… less so.

###The Code

public interface IGameInterfaceState
{
	
	void UpdateState();
	void ToPlayState();
void ToChatState();
	void ToStatisticsState();
	void ToPausedState();

}

###More Code

public class GameplayUserInterface : MonoBehaviour 
    {
    	[HideInInspector] public IGameInterfaceState CurrentState;
    
    	[HideInInspector] public PlayState PlayState;
//    	... ETC
    
    	public Texture2D Reticle;
    	public float ReticleScale = 1;
    
    	[HideInInspector] public DisplayReticle DisplayReticle;
    
    	private void Awake()
    	{
    		PlayState = new PlayState (this);
    		ChatState = new ChatState (this);
//    	        ... ETC

       		DisplayReticle = gameObject.GetComponent<DisplayReticle>();
    	}
    
    	void Start()
    	{
    		CurrentState = PlayState;
    	}
    
    	void Update()
    	{
    		CurrentState.UpdateState();
    	}
    }

###State Interface

public class PlayState : IGameInterfaceState {

	public DisplayReticle displayReticle;

	private readonly GameplayUserInterface gameInterface;
	private Texture2D reticle;
	private float reticleScale;


	public PlayState (GameplayUserInterface gameplayUserInterface)
	{
		gameInterface = gameplayUserInterface;
	}

	private void Start()
	{
		reticle = gameInterface.Reticle;
		reticleScale = gameInterface.ReticleScale;

		displayReticle = gameInterface.DisplayReticle;
	}

	public void UpdateState()
	{
		ShowReticle ();
		ShowHealth ();
		ShowAmmo ();
		//... ETC
	}

	public void ToPlayState()
	{
		
	}

	public void ToChatState()
	{
		
	}
		
	private void ShowReticle()
	{
	}

###Reticle Code

public class DisplayReticle : MonoBehaviour
    {
    	private GameplayUserInterface gameInterface;
    	private Texture2D reticle;
    	private float reticleScale;
    
    	public DisplayReticle (GameplayUserInterface gameplayUserInterface)
    	{
    		gameInterface = gameplayUserInterface;
    	}
    
    	private void Start()
    	{
    		reticle = gameInterface.Reticle;
    		reticleScale = gameInterface.ReticleScale;
    	}
    
    	public void Display()
    	{
    		print ("Reticle - " + reticle);
    	}
    
    	public void OnGUI()
    	{
    		//Reticle Stuff Here...
    	}
    }

Super sorry for the code dump, I couldn’t see any way around it without knowing my shit… :expressionless:

I think I understand what you want in a way. As I believe your transitions aren’t dependent on the previous state you could do something like below. If they are dependent I would maybe consider how you set them up and try to make them not dependent. My mind feels clogged up at the moment but I would do something like this:

I’m a fan of abstract classes sooo… (because you can make classes require variables and you can define generic methods in them. Dont know if you need this functionality but I think likely that you might if not Interface is fine too)

public abstract class GameState {
   // All your logic for moving to a new state would go here.
   // Break down ui, deallocate, active = false, etc etc
   public void TransitionExit();

   // All your initialization code here
   public void TransitionEnter();

   // Same function as you currently have
   public void UpdateState();
}

Question one: What do you need to access and why? A state machine likely doesn’t need any outside information. If your question is how to make it so other classes can cause a transition then:

public GameplayUserInterface : Monobehaviour {
   public string CurrentState = "PlayState";
   // Instead of strings, could use a enum or int or anything.
   public Dictionary<string, GameState> stateMap = new Dictionary<string, GameState> {
      new PlayState(),
      new ChatState(),
      //etc,etc,etc
   };
   
   public void ChangeTransition(string state) {
      stateMap[CurrentState].TransitionExit();
      stateMap[state].TransitionEnter();
      CurrentState = state;
   }
}

Then for the transition settings, you could create scriptableobjects or prefabs or even classes for all the transitions that you might want to use. You would make a similar system as your GameState and make general methods that could be ran in TransitionEnter/Exit. How does the transition effects get decided upon? Predefined or random/different everytime?