Stop everything on first error + state machine

Let me explain,
I have a FSM called “GameStates” which basically sets up a bunch of things and then switches to the correct state. I also have many scripts which rely on it, for example, the state machine sends a message to my Managers class, which in turn caches everything I need and then tells the state machine when it’s done, and the state machine moves on.

All the scripts that rely on it are caching their own things on start, by accessing my Managers class and getting its components/cached scripts and objects.

But what I am currently doing in all these scripts is this, which I don’t like much:

private Transform player;
private Camera playerCam;

void Start () 
{
    if( !GameStates.initDone )
    {
        Debug.LogWarning("Initialization failed! Disabling " + this);
        this.enabled = false;
        return;
    }
    else
    {
        // Do what I need
        player = Managers.PC.transform;
        playerCam = Managers.Cameras.PlayerCam;
        etc...
    }
}

This works fine, but I hate having to add the check for successful initialization in every scripts that depend on it.

Is there another way I can ‘stop’ everything from only one main class, like my GameStates class? I’m not sure I’m doing this very efficiently, and it can also introduce a lot more user errors then if only one script took care of stopping everything that needs to be stopped.

Any suggestion is greatly appreciated as always, thanks for your time guys!

Stephane

So you have two choices listed here, by far the simplest is to take asafsitner’s BroadcastMessage concept when your initialisation is complete. This is a slow method, but you don’t really care as this happens only once. The event model is fast and works well if you need components to react to changes in your state machine on a regular basis.

Unity doesn’t have a “root” scene object, so it turns out that you should probably use a loop and SendMessage something like this:

Add Linq to your usings:

using Systen.Linq;

The when you’ve initialized

foreach(var go in GameObject.FindObjectsOfType(typeof(GameObject))
     .Cast<GameObject>())
{
	go.SendMessage("StateMachineInitialized",
          null, SendMessageOptions.DontRequireReceiver);
}

In each object you can now optionally add a void StateMachineInitialized() method to do what you need to do on initialization, like enabling things.

If you wanted to use events then to your state machine you would add some event definitions, in this case Initialized. I’m guess you have one master statemachine, if you had multiple this would be more tricky.

public class SomeStateMachine
{
     public static event Action Initialized = delegate {};

     void Start()
     {
          // Some kind of initialization

          Initialized();
     }
}

Your other objects subscribe to this event:

public class SomeOtherBehaviour : MonoBehaviour
{
    void Awake()
    {
          SomeStateMachine.Initialized += MethodCalledAfterInitialization;
    }

    void MethodCalledAfterInitialization()
    {
          // enable or whatever

          SomeStateMachine.Initialized -= MethodCalledAfterInitialization;
    }
}

You could have events for states changing etc.