Can't access variable from another script - c#

Assets\Scripts\Wood.cs(32,9): error CS0201: Only assignment, call, increment, decrement, await, and new object expressions can be used as a statement
Well I'm trying to take the bool hasTorch and put it in the script Wood.cs to know if the player has a torch or not.
(I'm new so it's probably easy to fix, I just don't know :c)
Script 1 (Chest.cs):
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Chest : MonoBehaviour
{
public Sprite openChest;
public GameObject chest1;
public GameObject chestBox;
public GameObject torch;
public bool hasTorch = false;
public GameObject darkness;
public GameObject chatBox;
private void OnTriggerEnter2D(Collider2D other)
{
chest1.GetComponent<SpriteRenderer>().sprite = openChest;
torch.SetActive(true);
chatBox.SetActive(true);
darkness.SetActive(false);
chestBox.SetActive(false);
hasTorch = true;
}
public void Close()
{
chatBox.SetActive(false);
}
}
Script 1 (Wood.cs):
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Wood : MonoBehaviour
{
public GameObject chestScript;
public Chest script;
public GameObject chatBox;
private void OnTriggerEnter2D(Collider2D other)
{
if (script.hasTorch == true)
{
chatBox.SetActive(true);
}
if (script.hasTorch == true)
{
chatBox.SetActive(true);
}
}
public void Close()
{
chatBox.SetActive(false);
}
void Start(){
chestScript.GetComponentInChildren<Chest>().hasTorch;
}
}

This line does not do anything (not a valid statement, as the error suggests):
chestScript.GetComponentInChildren<Chest>().hasTorch;
you could Log it or set it to true/false like this (a valid assignment):
chestScript.GetComponentInChildren<Chest>().hasTorch = false;

You have created a variable of type Chest but have not told Unity which Chest instance you want to access. Imagine you had a couple of GameObjects, all with this script attached, each with a different value for hasTorch. Unity wouldn't know which instance you have in mind, that is why you have to specifically assign the value.
All you have to do is to add this line into the Start() method:
script = someKindOfaGameObject.GetComponent<Chest>();
From now on you should be able to access all the public variables in the Chest script using script.variable syntax.

Related

How do I correctly pass a self reference of one object to another? [duplicate]

This question already has answers here:
What is a NullReferenceException, and how do I fix it?
(27 answers)
Closed 4 months ago.
I have a PlayerMovement class and an EnemyMovement class. My enemy moves only when the player moves.
When an enemy is created, it should get added to a list of enemies in the PlayerMovement object.
This is what I've got:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class EnemyMovement : MonoBehaviour
{
public PlayerMovement player;
void Awake()
{
player.Subscribe(this);
}
public void Move()
{
print("Enemy moved!");
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerMovement : MonoBehaviour
{
public static ArrayList enemies;
void Start()
{
enemies = new ArrayList();
}
void Message(Direction direction)
{
foreach(EnemyMovement enemy in enemies)
{
enemy.Move();
}
}
public void Subscribe(EnemyMovement enemy)
{
enemies.Add(enemy);
}
}
However, Unity gives me the error
NullReferenceException: Object reference not set to an instance of an object.
How do I correctly pass a self reference of one object to another?
Where I’m relying on myself, or another user, to enter references through the Inspector, I generally like to add checks to the code. For example:
public class EnemyMovement : MonoBehaviour
{
public PlayerMovement player;
void Awake()
{
if (player == null)
{
Debug.LogError ( “PlayerMovement is null.” );
return;
}
player.Subscribe(this);
}
// ..
}
And then if I know I want an initialised item from the start, I will generally do so in the definition, like so:
public class PlayerMovement : MonoBehaviour
{
public static ArrayList enemies = new();
// ..
}
That way you stand a much smaller chance of getting a NullRegerence exception.

DialogueTrigger.Text is a field, but a type was expected+

I'm making a dialogue system in unity, in which a player would walk up to an NPC and press E to trigger a dialogue response, However, when I attempt to access the "Text" Component of the GameObject, I receive two of the same errors:
Assets/DialogueTrigger.cs(28,24): error CS0118: DialogueTrigger.Text is a field' but a `type' was expected
This is the component I am trying to access:
Text (Script)
The component is in This game object:
Game Object
Here is the code:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class DialogueTrigger : MonoBehaviour {
public string Text;
public string Name;
public GameObject Dialog;
public GameObject Texta;
public GameObject Namea;
public Collider2D collision;
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update () {
}
void OnTriggerEnter2D(Collision col)
{
if (Input.GetKeyDown(KeyCode.E))
{
Dialog.SetActive(true);
Texta.GetComponent<Text>().Text = "Hello!";
Namea.GetComponent<Text>().Text = "Guy";
}
}
}
Any solutions are greatly appreciated.
There's a name conflict between your field named 'Text' and the component type 'Text', so the compiler doesn't understand which one you meant by GetComponent<Text>().
You can resolve this by changing the name of your field to something else, like for example 'text'.
You also don't even need to call GetComponent<Text>() if you change the types of your Texta and Namea fields to Text.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class DialogueTrigger : MonoBehaviour {
public string Text;
public string Name;
public GameObject Dialog;
public Text Texta;
public Text Namea;
public Collider2D collision;
void OnTriggerEnter2D(Collision col)
{
if(Input.GetKeyDown(KeyCode.E))
{
Dialog.SetActive(true);
Texta.text = "Hello!";
Namea.text = "Guy";
}
}
}

is there a way to find if an object in an array has been destroyed? [duplicate]

I'm creating a game and i want to show a panel when the player is dead
I've tried different approaches but none seems to do what I want
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class DeadOrAlive : MonoBehaviour
{
public GameObject Player;
public GameObject deadPanel;
void Update()
{
if (!GameObject.FindWithTag("Player"))
{
deadPanel.SetActive(true);
}
}
}
To check if a object has been destroyed, you should use MonoBehavior's OnDestroy like so:
// Attach this script to the player object
public class DeadOrAlive : MonoBehaviour
{
public GameObject deadPanel;
void OnDestroy()
{
deadPanel.SetActive(true);
}
}
You can also instead of destroying the player object, set it to active/inactive, but to check if the player is dead or alive this way, you will need a separate object which checks the active state:
//Attach this to a object which isn't a child of the player, maybe a dummy object called "PlayerMonitor" which is always active
public class DeadOrAlive : MonoBehaviour
{
public GameObject deadPanel;
void Update()
{
if (!GameObject.FindWithTag("Player"))
{
deadPanel.SetActive(true);
}
}
}
Haven't used unity in a while and forgot how weird it could get.
Thanks to #VincentBree this is how I did it
void Update()
{
if (!Player.activeSelf)
{
deadPanel.SetActive(true);
}
}

Is there a way to check if a GameObject has been destroyed?

I'm creating a game and i want to show a panel when the player is dead
I've tried different approaches but none seems to do what I want
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class DeadOrAlive : MonoBehaviour
{
public GameObject Player;
public GameObject deadPanel;
void Update()
{
if (!GameObject.FindWithTag("Player"))
{
deadPanel.SetActive(true);
}
}
}
To check if a object has been destroyed, you should use MonoBehavior's OnDestroy like so:
// Attach this script to the player object
public class DeadOrAlive : MonoBehaviour
{
public GameObject deadPanel;
void OnDestroy()
{
deadPanel.SetActive(true);
}
}
You can also instead of destroying the player object, set it to active/inactive, but to check if the player is dead or alive this way, you will need a separate object which checks the active state:
//Attach this to a object which isn't a child of the player, maybe a dummy object called "PlayerMonitor" which is always active
public class DeadOrAlive : MonoBehaviour
{
public GameObject deadPanel;
void Update()
{
if (!GameObject.FindWithTag("Player"))
{
deadPanel.SetActive(true);
}
}
}
Haven't used unity in a while and forgot how weird it could get.
Thanks to #VincentBree this is how I did it
void Update()
{
if (!Player.activeSelf)
{
deadPanel.SetActive(true);
}
}

How could i fix an error (cs0120) in unity?

In unity, I'm trying to make a press of a button increase the speed of the player. However, each time I run it. It gives me:
Error CS0120: An object reference is required for the non-static
field, method, or property 'PlayerController.speed'
I've already tried changing order of the code, so what could I do?
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Upgrader1 : MonoBehaviour
{
void Start()
{
GameObject Player = GameObject.Find("Player");
PlayerController PlayerController = Player.GetComponent<PlayerController>();
}
public void Upgrade1()
{
PlayerController.speed++;
}
}
public class Upgrader1 : MonoBehaviour
{
PlayerController PlayerController; //It should be member variable
void Start()
{
GameObject Player = GameObject.Find("Player");
PlayerController = Player.GetComponent<PlayerController>();
}
public void Upgrade1()
{
PlayerController.speed++;
}
}
it's always a good thing to use proper naming conventions.
PlayerController _PlayerController;
void Start() {
GameObject Player = GameObject.Find("Player");
_PlayerController = Player.GetComponent<PlayerController>();
}
public void UpgradeSpeed() // I changed the name according to its functionality
{
_PlayerController.speed++;
}
With this, you won't put PlayerController class reference again by mistake.

Categories