How do I call methods from other scripts using C#?

I’m seriously stuck with this. I have 2 scripts; a Game Manager and a UI Manager. When you hit Esc the ‘gamestate’ in the Game manager is set to paused and from within it will call a method from the UI manager to display a ‘paused’ message on the screen.

I have 2 scenes. In the first scene which is the main menu, the Game manager is initialised and continue to exist throughout every scene. In the second scene, there is a empty game object with the UI Manager attached.

When I run the game, move to level 1, and the hit escape, I get the following errors:

NullReferenceException: Object reference not set to an instance of an object
Game_Manager.GamePause () (at Assets/Scripts/Game_/Game_Manager.cs:55)
Game_Manager.Update () (at Assets/Scripts/Game_/Game_Manager.cs:46)

So it’s claiming that the UI Manager does not exist and so it crashes. :frowning:

Here are the scripts…

/// Game Manager

using System.Collections;
using UnityEngine;

enum GameState { mainmenu, playing, paused, gameover };

public class Game_Manager : MonoBehaviour
{
    private static Game_Manager thisInstance;
    private static GameState mGameState;
    private UI_Manager mUI;
    

    void Awake()
    {
        Screen.SetResolution(800, 600, false);

        /// Ensures that the GameManager is persistant through all scenes
        
        if (thisInstance != null && thisInstance != this) //IF we already has an instance of this class
            Destroy(gameObject);
        else
        {
            thisInstance = this;
            DontDestroyOnLoad(this);
        }
    }

    void Start()
    {
        Debug.Log("Game_Manager initialised");
        mGameState = GameState.mainmenu;
    }

    void Update()
    {
        if (mGameState == GameState.mainmenu)
        {
            GameMainMenu();
        }

        /// Pausing
        if (Input.GetKeyDown(KeyCode.Escape))
        {
            GamePause();
        }
    }

    public void GamePause()
    {
        if (mGameState == GameState.playing)
        {
            mUI.GamePauseGUI();
            Time.timeScale = 0.0f;
            mGameState = GameState.paused;
            Debug.Log("Game Paused");
        }
        else
        {
            Time.timeScale = 1f;
            mGameState = GameState.playing;
            Debug.Log("Game Playing");
        }
    }

    void GameMainMenu()
    {
        
        if (Input.anyKeyDown)
        {
            Application.LoadLevel(1);
            mGameState = GameState.playing;
        }
    }

    public static Game_Manager Instance
    {
        get
        {
            if (thisInstance == null)
            {
                thisInstance = new GameObject("MySingleton").AddComponent<Game_Manager>();
            }

            return thisInstance;
        }
    }

    public void OnApplicationQuit()
    {
        thisInstance = null;
    }
}



// UI_Manager

using UnityEngine;
using System.Collections;

public class UI_Manager : MonoBehaviour {

	// Use this for initialization
	void Start () {
        
	}
	
    void OnGUI()
    {

    }

    void Update()
    {

    }

    public void GamePauseGUI()
    {
        Debug.Log("Game Paused GUI");
    }
}

My guess is that it is comming from this line:

mUI.GamePauseGUI();

Unity does not automatically connect references except for built in accessors such as .transform. You need to manually reference the UI_Manager GameObject in order to use it. This can be done a number of ways, here’s an example.

public class Game_Manager : MonoBehaviour
{
    private static Game_Manager thisInstance;
    private static GameState mGameState;
    //-------------------------
    private UI_Manager mUI;
    private UI_Manager MUI {
        get {
            if(mUI == null) {
                 mUI = (UI_Manager)FindObjectOfType(typeof(UI_Manager));
                  //^ this is the important line.
            }
            return mUI;
        }
    }
    //-------------------------

    public void GamePause() { /*use the property MUI to call your methods*/ }
}

The important part of the above example is mUI = (UI_Manager)FindObjectOfType(typeof(UI_Manager));. The method finds an object of the given type in the scene and returns it. You need to cast it to its derived type though 95% of the time before you actually use it.

Thanks. Works perfectly!