-1

Hello more experienced coders! I've run into this C# error in Unity and have been unable to understand why. I'm an absolute beginner, so even when reading other answers here, I haven't been able to grasp how or why any of the solutions work or how to implement them. Here's what I've got.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class HealthStatusBar : MonoBehaviour
{

    public PlayerController mainHealth;
    public Image fillImage;
    private Slider slider;

    void Awake()
    {
        slider = GetComponent<Slider>();
    }

    // Update is called once per frame
    void Update()
    {
        float fillValue = PlayerController.mainHealth / PlayerController.maxHealth;
        slider.value = fillValue;
    }
}

The script above is giving me the problem. This line specifically.

float fillValue = PlayerController.mainHealth / PlayerController.maxHealth;
        slider.value = fillValue;

Here's the relevant portion from my other script.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class PlayerController : MonoBehaviour
{

    public float speed;
    public float jumpForce;
    private float moveInput;

    private Rigidbody2D rb;

    private bool facingRight = true;

    private bool isGrounded;
    public Transform groundCheck;
    public float checkRadius;
    public LayerMask whatIsGround;

    private int extraJumps;
    public int extraJumpValue;

    //Health

   public int mainHealth;
   public int maxHealth;

    //Health

    void Awake()
    {
        mainHealth = maxHealth;
    }

I've tried making mainHealth and maxHealth static which fixes the error, but that removes the ability to change the value in Unity's editor. I'm sure this is a super simple solution, but this is the second time I've encountered this error and have been unable to resolve it. If anyone can explain this in better detail, that would be greatly appreciated.


Edit: The CS0120 error has been resolved. PlayerController.mainHealth needed to be changed to mainHealth.mainHealth. However, I am now getting a Null Reference Exception from the same troublesome line of code.

Enigmativity
  • 113,464
  • 11
  • 89
  • 172
  • 1
    You're going to need to show us more code. None of the code you show is `static`, so that error shouldn't happen (given the code you show). What does the class that contains `mainHealth` and `maxHealth` look like? What does the code where the error occurs look like (and point out which line it occurs in). For what it's worth, having two things, typed differently, but both named `mainHealth` will eventually cause you confusion – Flydog57 Sep 21 '20 at 23:51
  • Please don't edit your question with an attempt to change the problem and hence invalidate existing answers. I've moved your edit to the bottom of the question to help maintain clarity, but you should ask a new question if the question you asked has been resolved and a new one appeared. – Enigmativity Sep 22 '20 at 00:47
  • And, now that you've introduced the issue of a `NullReferenceException`, I've now closed the question as a duplicate. I think you've got your complete answer now, in any case. – Enigmativity Sep 22 '20 at 00:49
  • @Enigmativity though now the title and duplicate are a bit mismatched ^^ I'll add a duplicate for the original issue as well – derHugo Sep 22 '20 at 05:59
  • 1
    @derHugo - And this is why it is not the right practice to ask a follow on question by editing the question. A follow on question should be a new one. – Enigmativity Sep 22 '20 at 06:11
  • 1
    @Enigmativity that is also true of course ;) – derHugo Sep 22 '20 at 06:12

2 Answers2

2
float fillValue = PlayerController.mainHealth / PlayerController.maxHealth;

This line is trying access mainHealth and maxHealth from the PlayerController class, both non-static variables, as if they are static. What you actually are trying to do is access the main and max health on a specific PlayerController object right? I assume so since you have a PlayerController reference at the top of the HealthStatusBar class called "mainHealth" itself. In that case, you need to change the fill value line to:

float fillValue = mainHealth.mainHealth / mainHealth.maxHealth;

Basically, PlayerController is a class, not a variable. When you put a dot after it you are trying to access the script directly. Thus any variables or methods you are accessing must be static so that it's the same across all PlayerController objects. If you want to access a variable on a specific object of PlayerController, then you need to create a reference to that specific object and put that dot after that reference instead of after the class name.

Thomas Finch
  • 482
  • 2
  • 6
  • This worked! I now have a Null Reference Exception. But it worked. – Eric Gustaf Sep 22 '20 at 00:35
  • "PlayerController is a script" - No, it's not a script. It's a class. – Enigmativity Sep 22 '20 at 00:38
  • Just gotta assign the object with the PlayerController on it in inspector or get it some other way (like GetComponent). @Enigmativity It is also a script in this case, but yeah class would have been more accurate. – Thomas Finch Sep 22 '20 at 00:48
  • @ThomasFinch - What makes you say it's a script? – Enigmativity Sep 22 '20 at 00:50
  • To be clear on how to solve the null reference exception. The variable (reference) you made to PlayerController called "mainHealth" previously. Let's assume you renamed that to "player" which I also recommend. In the unity inspector for the object with HealthStatusBar you will find that as a variable. Now, whatever object that has PlayerController on it, you need to drag into the "player" slot in the inspector. Then it will no longer be null and will be referring to the intended object. – Thomas Finch Sep 22 '20 at 00:51
  • @Enigmativity Because it's likely also the name of the script. I've updated the answer though, because I agree class is the accurate thing to say when I'm talking about it as a class not a script. – Thomas Finch Sep 22 '20 at 00:55
  • 1
    @ThomasFinch Yes! This seems to have been the issue. I had previously assigned in the Inspector but it must have reloaded or removed it some how. Thank you very much for the help! – Eric Gustaf Sep 22 '20 at 00:56
1

Before;

    public PlayerController mainHealth;
    ...
    float fillValue = PlayerController.mainHealth / PlayerController.maxHealth;
        slider.value = fillValue;

PlayerController is a type name, so the compiler is looking for a static field on that type. However the compiler discovered an instance field. Your local PlayerController variable is called mainHealth, so mainHealth.mainHealth would work.

Though I would recommend renaming that variable;

    public PlayerController player;
    ...
    float fillValue = player.mainHealth / player.maxHealth;
        slider.value = fillValue;
Jeremy Lakeman
  • 9,515
  • 25
  • 29