Event Subscription Not Working

I can’t figure out where I’ve gone wrong. I have a GameScreen MonoBehaviour, which is a generic component handled by a GameStateManager. I create specific GameScreens by creating a prefab and adding another MonoBehaviour which subscribes to the GameScreen’s events.

The following is the ‘generic’ GameScreen component.

/* GameScreens are used by the GameStateManager to display various game states */
public class GameScreen : MonoBehaviour
{
    #region Fields
    
    /* If true, input reaching this GameScreen will be blocked from following GameScreen */
    public bool blocksInput = false;
    
    /* Triggered when the GameScreen is entered */
    public System.EventHandler entered;
    
    /* Triggered when the GameScreen is exited */
    public System.EventHandler exited;
    
    /* Triggered when the GameScreen should handle input */
    public System.EventHandler handlingInput;
    
    #endregion
    
    #region Methods
    
    /* Insruct the GameScreen to handle player input */
    public void HandleInput()
    {
        print ("GameScreen.HandleInput");
        if (handlingInput != null)
            handlingInput(this, System.EventArgs.Empty);
    }
    
    /* Called when the GameScreen is entered */
    public void OnEntered()
    {
        print ("GameScreen.OnEntered");
        if (entered != null)
            entered(this, System.EventArgs.Empty);
    }
    
    /* Called when the GameScreen is exited */
    public void OnExited()
    {
        print ("GameScreen.OnExited");
        if (exited != null)
            exited(this, System.EventArgs.Empty);
    }
    
    #endregion
}

The following is a specific PauseScreen (for testing):

[RequireComponent(typeof(GameScreen))]
public class PauseScreen : MonoBehaviour
{
    #region Fields
    
    /* Should the PAUSE gui be shown? */
    private bool showGui = false;
    
    #endregion
    
    #region Methods
    
    /* Initialize */
    private void Awake()
    {
        GameScreen gs = GetComponent<GameScreen>();
        gs.entered += OnEntered;
        gs.exited += OnExited;
        gs.handlingInput += OnHandleInput;
    }
    
    #endregion
    
    #region Event Handlers
    
    /* Called when the GameScreen should handle input */
    public void OnHandleInput(object sender, System.EventArgs e)
    {
        print ("PauseScreen.OnHandleInput");
        if (Input.GetKey(KeyCode.Escape))
            GameStateManager.instance.PopGameScreen(GetComponent<GameScreen>());
    }
    
    /* Called when the GameScreen is entered */
    public void OnEntered(object sender, System.EventArgs e)
    {
        print ("PauseScreen.OnEntered");
        BCTime.SetTimeScale(TimeZone.Core, 0f);
        showGui = true;
    }
    
    /* Called when the GameScreen is exited */
    public void OnExited(object sender, System.EventArgs e)
    {
        print ("PauseScreen.OnExited");
        BCTime.SetTimeScale(TimeZone.Core, 1f);
        showGui = false;
    }
    
    /* Draw GUI */
    private void OnGUI()
    {
        if (!showGui) return;
        
        // DRAW PAUSE GUI
    }
    
    #endregion
}

The GameStateManager simply calls OnEntered() / OnExited() / HandleInput() appropriately on the GameScreen instance, and the events should cause the corresponding methods to be called on the PauseScreen instance. The events don’t seem to be working, however.

I get the output from the print(); statements in GameScreen as expected, but nothing at all from PauseScreen.

I’m stumped why?

Okay, so I solved my particular problem but I’m confused why it’s a problem:

My GameObject representing the pause screen is a GameObject containing both a GameScreen and PauseScreen as components.

It is passed to a method in the GameStateManager by dragging and dropping the UNINSTANTIATED prefab from the Project view to the active GameStateManager instance’s pauseScreenGameObject field.

When the game is run, GameStateManager calls pauseScreenGameObject.OnEnabled() and that method runs fine but it appears the Awake() method is not called on the PauseScreen component.

I don’t understand what’s going on here and why, and I’m hoping someone can explain.

EDIT: Actually Awake() isn’t being called on any of the components attached to that prefab.

1 Like