- Home /
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. :(
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");
}
}
Answer by Peter G · Jun 11, 2011 at 05:07 PM
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.
Answer by AaronG · Jun 11, 2011 at 05:10 PM
Thanks. Works perfectly!
$$anonymous$$ake sure to mark it the correct answer then. A checkmark outline should show up under the votes for my answer that you need to click on.