Search code examples
c#unity-game-engineruntime-errormonodevelop

Code not allowing letting me disable a script from another script


I'm having an issue where I can't disable a script from the other script - they are both public and within the same package (I think).

Here is my code for the script I'm trying to disable from:

using UnityEngine;
using System.Collections;
using UnityEngine.UI;
#if UNITY_EDITOR
using UnityEditor;
#endif
using RTS;

public class PauseMenu : MonoBehaviour {

Canvas canvas;
private Player player;
public Button Button2;


void Start()
{
    Debug.Log ("asdf");
    player = transform.root.GetComponent< Player >();
    canvas = GetComponent<Canvas>();
    canvas.enabled = false;
    ResourceManager.MenuOpen = false;
    Button2.GetComponent<Button>().onClick.AddListener(() => { Resume();});
    if(player) player.GetComponent< UserInput >().enabled = false;
}

And the code for the other script:

//sets up what resources we are using
using UnityEngine;
using System.Collections;
using RTS;

public class UserInput : MonoBehaviour {

//sets up a private variable for only this class - our player
private Player player;

// Use this for initialization
void Start () {
//this goes to the root of the player ie the object player and allows us to
player = transform.root.GetComponent< Player > ();
}//end Start()

So the part that is not working is:

if(player) player.GetComponent< UserInput >().enabled = false;

And the code runs and then causes the runtime error:

NullReferenceException: Object reference not set to an instance of an object
PauseMenu.Pause () (at Assets/Menu/PauseMenu.cs:40)
PauseMenu.Update () (at Assets/Menu/PauseMenu.cs:29)

Here is a picture showing my scene hierarchy and components: Scene hierarchy


Solution

  • The issue here is that you try to execute transform.root.GetComponent< Player >(); from within PauseMenu, which is on the "Canvas" object.

    The problem with that is that the topmost transform in the hierarchy of your "Canvas" object (which is what transform.root returns) is, well, the transform of the "Canvas" object - which is in no way related to the UserInput script you are trying to access. For this script to actually work, you would need the transform of your "Player" object, which is the object that actually has the UserInput script.

    My suggestion is to eliminate the need to run GetComponent() at all - create a public UserInput variable in your PauseMenu class, then (while selecting your "Canvas") in the editor, drag the "Player" object into that new field. This will cause the UserInput script of your "Player" object to be accessible within the PauseMenu.

    So your PauseMenu script might look like:

    public class PauseMenu : MonoBehaviour {
    
        Canvas canvas;
        public UserInput playerInput; // Drag the Player object into this field in the editor
        public Button Button2;
    
        void Start()
        {
            Debug.Log ("asdf");
            canvas = GetComponent<Canvas>();
            canvas.enabled = false;
            ResourceManager.MenuOpen = false;
            Button2.GetComponent<Button>().onClick.AddListener(() => { Resume();});
            playerInput.enabled = false;
        }
    }
    

    Hope this helps! Let me know if you have any questions.

    (An alternative is to use GameObject.Find("Player") to get GameObject of "Player". This needs a bit more code but doesn't use the editor.)