Code not allowing letting me disable a script from another script - c#

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:

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.)

I would say your player = transform.root.GetComponent< Player >(); arrives null.
So you are trying to disable something that doesnt exist.
Enter debug mode and see if your player is null or not.

Related

How to display Debug.Log messages on Text.UI after restarting the same scene? [duplicate]

This question already has answers here:
What is a NullReferenceException, and how do I fix it?
(27 answers)
Closed 1 year ago.
I'm working on a simple little game in Unity where the objective is to use a floating hand to guide the ball into the basket and every time the ball enters the basket, the game resets due to an hidden collider with a trigger inside the basket.
The feature I'm trying to implement:
Every time the ball goes into the basket the text.UI updates to reflect your new score, beginning with 0 points and the score increments by 1 for every slam dunk.
The issue:
How do I convert the "Debug.Log" into a text.UI?
I was only successful in updating the score on the Unity console and I wasn't able to convert these events to the text.UI.
The text.UI GameObject I've created only displays the text "New Game" and never gets updated.
Update: I've created a new script to solve this and I got this error:
NullReferenceException: Object reference not set to an instance of an object
ChangingText.Start () (at Assets/Scripts/ChangingText.cs:12)
The process:
1. Creating a GameObject and script to keep data after scene restarts.
I've created a script to keep the score after restarting the the same scene, I have only one scene.
I've attached this script to the game object: "GameController" and that's how was able to keep the score updated.
The name of the scene is:
"DunkingPractice"
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class GameControl : MonoBehaviour
{
// Giving it a name called "Control", any other script can interact with it
public static GameControl Control;
public int score;
// Called before Start()
private void Awake()
{
// If there's a control already, delete this
// If there's no control, make this the control object
if (Control == null)
{
Control = this;
DontDestroyOnLoad(gameObject); // Don't destory the object when a scene is loaded
}
else if (Control != this)
{
Destroy(gameObject);
}
}
}
Image that I've included to demonstrate this:
Creating "GameController" GameObject and Script
2. Creating an hidden trigger collider GameObject inside the basket with a scenemanager.loadscene inside the script
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
public class RestartTrigger : MonoBehaviour
{
void OnTriggerEnter2D(Collider2D collision)
{
if (collision.tag == "Ball")
{
SceneManager.LoadScene(0);
}
}
}
Image that I've included to demonstrate this:
Creating a trigger collider and restart trigger
3. Creating a script to Keep score and adding this component to the aforementioned trigger collider
Notice that the script refers to the Game Control script I've created earlier.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class KeepingScore : MonoBehaviour
{
static void OnTriggerEnter2D(Collider2D collision)
{
if(collision.tag == "Ball")
{
GameControl.Control.score++;
if (GameControl.Control.score == 1)
{
Debug.Log("You have " + GameControl.Control.score + " point");
}
else if (GameControl.Control.score != 1)
{
Debug.Log("You have " + GameControl.Control.score + " points");
}
}
}
}
Here's another image that I've included:
Creating a script to keep score and attaching it to the trigger field
4. Creating a Text.UI on screen and creating a new script to change text only for an error to appear
This is the script that produces the NullReferenceException error:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class ChangingText : MonoBehaviour
{
public Text scoreText;
void Start()
{
scoreText.text = GameControl.Control.score.ToString();
}
}
Here's another image to demonstrate:
Creating a text object
Here's a screen recording I've made to show how my scene currently looks like:
https://www.screencast.com/t/JUBsUkHuHgHC
Do you have any suggestions?
Thank you
NullReferenceException is happened if one of your instance is null and you are trying to modify it, in the log error, it show that :
Object reference not set to an instance of an object ChangingText.Start ()
It means that your scoreText instance does not connect to any UI and it's null. To resolve that, just simply create text UI gameObject and drag it into the 'scoreText' field in the object that is assigned with ChangingText script

Can't load prefab in Unity Editor

I am trying to make an [ExecuteInEditMode] script spawn game objects (linked to the same prefab) at specific positions right in the Editor so that I can quickly create different hexagon tile maps by just triggering booleans in the inspector. However, the Resources.Load() method cannot not find the prefab even though the path is correct and so I get the following error:
NullReferenceException: Object reference not set to an instance of an object.
Here is the code:
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
[ExecuteInEditMode]
public class PositionChecker : MonoBehaviour
{
[SerializeField] float tileGap = 1.5f;
[SerializeField] GameObject tilePrefab; // alternatively tried dragging the prefab in the field in the inspector - it worked
[SerializeField] bool tileUpLeft;
GameObject tilesParent;
private void Awake()
{
tilesParent = GameObject.Find("All Tiles");
tilePrefab = Resources.Load("Assets/Prefabs/Tile.prefab") as GameObject;
}
// Update is called once per frame
void Update()
{
CheckForCreateTile();
}
private void CheckForCreateTile()
{
if (tileUpLeft)
{
tileUpLeft = false;
InstantiateTilePrefab(new Vector3(transform.position.x - 0.6f * tileGap, transform.position.y, transform.position.z - tileGap));
}
}
private void InstantiateTilePrefab(Vector3 vector3)
{
GameObject newTile = PrefabUtility.InstantiatePrefab(tilePrefab, tilesParent.transform) as GameObject;
Debug.Log(tilePrefab); // null
Debug.Log(tilesParent); // ok
Debug.Log(newTile); // Null
newTile.transform.position = vector3;
}
}
If I drag the prefab onto the serialized field of each created tile manually in the inspector instead of trying to load it, everything works fine.
The asset has to be in a "Resources" folder. So to solve your problem you can put "Tile.prefab" into the folder "Assets/Resources" and use the relative path: Resources.Load("Tile.prefab");
https://docs.unity3d.com/ScriptReference/Resources.Load.html
The file-path string automatically starts with "Resources/". So you shouldn't type that in. Also I don't think unity likes the file type in the string so don't type that in either. This works for me:
GameObject tilePrefab;
tilePrefab = Resources.Load<GameObject>("Prefabs/Tile");
GameObject tile = Instantiate(tilePrefab, Vector3.zero, Quaternion.identity);

Trying to interact with a component on object hit by raycast, getting NullReferenceException

I have a problem with my character when it interacts with a box. I have a GameObject Player with a script attached to it to interact with boxes in the game, the script is:
using UnityEngine;
using System.Collections;
public class PlayerBox : MonoBehaviour {
public bool active = true;
public KeyCode key = KeyCode.E;
float distance = 2F;
RaycastHit obj;
BoxManager box;
void Start () {
box = GetComponent<BoxManager>();
}
void Update () {
if (active && Input.GetKeyDown (key) && Physics.Raycast (this.transform.position, this.transform.forward, out obj, distance)) {
if (obj.collider.gameObject.tag == "Box") {
box.Open();
Debug.Log("aperto " + box);
}
}
}
}
In the scene there is a GameObject Box with a script to manage the behaviour:
using UnityEngine;
using System.Collections;
public class BoxManager : MonoBehaviour {
public void Open() {
Debug.Log ("Dentro");
}
}
The last script should print the log but when I interact with it I get
NullReferenceException: Object reference not set to an instance of an object
PlayerBox.Update () (at Assets/ETSMB/Script/Use/PlayerBox.cs:23)
How can I correctly set box to an instance of an object?
The issue here is that you're looking in the wrong place for the BoxManager component when you assign a value to box in your Start() method:
void Start () {
box = GetComponent<BoxManager>();
}
GetComponent<BoxManager>() will search for the component BoxManager on the current script's GameObject (the GameObject of PlayerBox, in this case). However, based on your wording it sounds like BoxManager and PlayerBox are on two different GameObjects, so you can't find the component this way. Trying to do so will just give box a value of null, which is the reason behind the NullReferenceException when you call box.Open().
What you need to do instead is retrieve BoxManager from the object you get back from Physics.Raycast() - so remove what's in your Start() method, and rewrite the contents of your Update() method to:
void Update () {
if (active && Input.GetKeyDown (key) && Physics.Raycast (this.transform.position, this.transform.forward, out obj, distance)) {
if (obj.collider.gameObject.tag == "Box") {
// Get the BoxManager from the object that has been hit
box = obj.collider.gameObject.GetComponent<BoxManager>();
box.Open();
Debug.Log("aperto " + box);
}
}
}
Hope this helps! Let me know if you have any questions.
Problem is:
void Start () {
box = GetComponent<BoxManager>();
}
is looking for a BoxManager component on PlayerBox, not your BoxManager game object in the scene. So, if there's not a BoxManager script on the PlayerBox game object, box will be null. Hence, your error message.
There are a number of ways to find objects in the scene (see: FindObjectsOfType) but the simplest for your example would be to make BoxManager box public:
public BoxManager box;
void Start () {
//box = GetComponent<BoxManager>();
}
Then, in the unity editor, drag and drop the BoxManager object from the scene hierarchy onto the box variable of the PlayerBox object's inspector.
Now everything is wired up and you shouldn't get a null pointer exception anymore.

Instantiate a gameobject as Child

I'm working on a 2D UI application with Unity and i have a problem.
I was working on the script to instantiate my popup window (i made a prefab). And i succeed but later Unity crashed and i had to redo my scene (forgot to ctrl+s)
Since this crash, my popup isn't instantiate as a child of my canvas and i've got this message:
"Setting the parent of a transform which resides in a prefab is disabled to prevent data corruption"
Here is my script :
using UnityEngine;
using System.Collections;
public class Popup : MonoBehaviour
{
public RectTransform popupPrefab;
private Animator anim;
// Use this for initialization
void Start()
{
//get the animator component
anim = popupPrefab.GetComponent<Animator>();
//disable it on start to stop it from playing the default animation
anim.enabled = false;
}
public void CreatePopup()
{
// Copie du prefab
RectTransform newPopup = Instantiate(popupPrefab, popupPrefab.transform.position, popupPrefab.transform.rotation) as RectTransform;
newPopup.transform.SetParent(transform, false);
//anim = newPopup.GetComponent<Animator>();
//anim.enabled = true;
//anim.Play("Popup");
}
public void ClosePopup()
{
anim.enabled = true;
anim.Play("ClosePopup");
}
}
I don't understand why i have this error since it was working fine before crash...
if you have any idea
Thanks
I solved the problem by re-doing my project from the beginning...

unity3d - how to create a terrain from a c# script

I'm looking to create a piece of terrain in unity using only a script (c# preferably) to do this rather than the menu options on the editor. So far I only have this code below, but I don't know what to do next to get it to appear on the scene, can anyone help?
Thank you
using UnityEngine;
using System.Collections;
public class terraintest : MonoBehaviour {
// Use this for initialization
void Start () {
GameObject terrain = new GameObject();
TerrainData _terraindata = new TerrainData();
terrain = Terrain.CreateTerrainGameObject(_terraindata);
}
// Update is called once per frame
void Update () {
}
}
Simply adding :
Vector3 position = ... //the ingame position you want your terrain at
GameObject ingameTerrainGameObject = Instantiate(terrain, position, Quaternion.identity);
should make the terrain appear ingame. The Instantiate method returns a reference to the gameobject spawned ingame, so if you later want to access it, you can use that reference.

Categories

Resources