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

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.

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.

Can't access variable from another script

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.

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 to properly make variable Public so it can be accessed by another script?

In Unity I have 2 GameObjects, a sphere and a capsule.
And I have a script attached to each.
Capsule script:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CapsuleMesh : MonoBehaviour
{
public Mesh capsuleMesh;
void Awake()
{
capsuleMesh = GetComponent<MeshFilter>().mesh;
Debug.Log(capsuleMesh);
}
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
}
}
Sphere script:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ChangeMesh : MonoBehaviour
{
Mesh mesh;
void Awake()
{
mesh = GetComponent<MeshFilter>().mesh;
Debug.Log(mesh);
}
// Start is called before the first frame update
void Start()
{
mesh = capsuleMesh;
}
// Update is called once per frame
void Update()
{
}
}
The mesh = capsuleMesh here is giving me an error about "the name capsuleMesh does not exist in the current context".
I thought that making capsuleMesh public in the other script would make THIS script be able to access it without issue.
What am I doing wrong?
capsuleMesh is a class variable defined in the CapsuleMesh class. It's not a global variable you can use everywhere. You need a reference to the instance of the CapsuleMesh class to retrieve the mesh stored in the capsuleMesh variable.
I've reworked your both scripts to make them work. I've spotted a flaw in your scripts. I guess ChangeMesh is meant to change the mesh of the gameObject? If so, you need to assign a new value to the meshFilter.mesh. Assigning a new reference to the mesh class variable is not enough (it would be pretty long to explain why)
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CapsuleMesh : MonoBehaviour
{
public Mesh Mesh
{
get ; private set;
}
void Awake()
{
Mesh = GetComponent<MeshFilter>().mesh;
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ChangeMesh : MonoBehaviour
{
// Drag & drop in the inspector the gameObject holding the `CapsuleMesh` component
public CapsuleMesh CapsuleMesh;
private MeshFilter meshFilter;
void Awake()
{
meshFilter = GetComponent<MeshFilter>();
}
void Start()
{
meshFilter.mesh = CapsuleMesh.Mesh;
}
}

Categories