NullReference in script? Prefab is linked in inspector

Hey all!
I’m a starting developer, been having fun with Unity, C# and the tutorials from Brackeys for a few weeks now. Enjoying the hell out of the Making a Multiplayer FPS tutorials from Brackeys! With help from the 14th episode, I tried to implement an UI bar to show the players stamina, instead of the fuel from the tutorial. Turns out I get a “NullReferenceException: Object reference not set to an instance of an object PlayerUI.Update () (at Assets/Scripts/PlayerUI.cs:19)”. It’s driving me crazy since the code doesn’t give any errors while building, plus, yeah I made sure the right prefabs are connected in the inspector. Still, the stamina for the sprinting works, but the bar doesn’t. Been trying a few days now, but I don’t have much hair left. So I would like some help from any of you super smart people. Anyway, this is my PlayerController:

using UnityEngine;
using UnityEngine.Networking;
using System.Collections;
[RequireComponent(typeof(PlayerMotor))]

public class PlayerController : MonoBehaviour {
    [SerializeField]
    private float speed = 5f;
    [SerializeField]
    private float defaultSpeed = 5f;
    [SerializeField]
    private float runspeed = 10f;
    [SerializeField]
    private float staminaStopSpeed = 1f;
    [SerializeField]
    private float lookSensitivity = 3f;
    private bool cantSprint = false;
    private PlayerMotor motor;
    private Animator animator;
    [SerializeField]
    private float staminaAmount = 1f;
    private float staminaBurn = 0.3f;
    private float staminaRegen = 0.1f;
    private float staminaStopSec = 3f;
    //getter stamina
    public float GetStaminaAmount () {
        Debug.Log (staminaAmount);
        return staminaAmount;    
    }
    void Start () {
        motor = GetComponent<PlayerMotor>();
        animator = GetComponentInChildren<Animator>();
    }
    void Update () {
        //movement 3d vector
        float xMov = Input.GetAxis("Horizontal");
        float zMov = Input.GetAxis("Vertical");
        Vector3 movHorizontal = transform.right * xMov;
        Vector3 movVertical = transform.forward * zMov;

        //final movement vector
        Vector3 velocity = (movHorizontal + movVertical) * speed;

        //animate movement 
        animator.SetFloat("ForwardVelocity", zMov);

        //apply movement in player motor script
        motor.Move (velocity);
        float yRot = Input.GetAxisRaw("Mouse X");
        Vector3 rotation = new Vector3 (0f, yRot, 0f) * lookSensitivity;

        //apply rotation
        motor.Rotate(rotation);

        // CAMERA rotate
        float xRot = Input.GetAxisRaw("Mouse Y");
        float cameraRotationX = xRot * lookSensitivity;

        //apply camerarotation
        motor.RotateCamera(cameraRotationX);
        
        //apply run
        if (Input.GetButton ("Sprint") && cantSprint == false && staminaAmount > 0.05f) {
            //stamina burn
            staminaAmount -= staminaBurn * Time.deltaTime;
            speed = runspeed;
            animator.speed = 2f;
        } else {
            //stamina regen
            staminaAmount += staminaRegen * Time.deltaTime;
            speed = defaultSpeed;
            animator.speed = 1f;
        }
        //clamp stamina
        staminaAmount = Mathf.Clamp (staminaAmount, 0f, 1f);
        if (staminaAmount <= 0.05f) {
            cantSprint = true;
            Invoke("StaminaStop", staminaStopSec);
            animator.speed = 0.2f;
            cantSprint = false;
        }
        if (staminaAmount >= 1f) {
            speed = defaultSpeed;
            animator.speed = 1f;
        }
        //just to test if the stamina calculations are working
        GetStaminaAmount();
    }
    //stamina invoke method
    void StaminaStop() {
        speed = staminaStopSpeed;
        }
}

Then the playerSetup script:

using UnityEngine;
using UnityEngine.Networking;
[RequireComponent(typeof(PlayerManager))]
[RequireComponent(typeof(PlayerController))]

public class PlayerSetup : NetworkBehaviour {
    [SerializeField]
    Behaviour[] componentsToDisable;
    [SerializeField]
    string remoteLayerName = "RemotePlayer";
    [SerializeField]
    string dontDrawLayerName = "DontDraw";
    [SerializeField]
    GameObject playerGraphics;
    [SerializeField]
    GameObject playerUIPrefab;
    private GameObject playerUIInstance;
    Camera sceneCamera;
    
void Start() {
        if (!isLocalPlayer) {
            DisableComponents();
            AssignRemoteLayer();
        } else {
            sceneCamera = Camera.main;
            if (sceneCamera != null) {
                sceneCamera.gameObject.SetActive(false);
            }
            //disable player graphics for local player
            SetLayerRecursively (playerGraphics, LayerMask.NameToLayer(dontDrawLayerName));

            //create player UI
            playerUIInstance = Instantiate (playerUIPrefab);
            playerUIInstance.name = playerUIPrefab.name;

            //configure player UI
            PlayerUI ui = playerUIInstance.GetComponent<PlayerUI>();
            if (ui == null)
                Debug.LogError ("No player UI component on player prefab");
            ui.SetController (GetComponent<PlayerController>());
        }
        GetComponent<PlayerManager>().Setup();
    }
    void SetLayerRecursively (GameObject obj, int newLayer) {
        obj.layer = newLayer;
        foreach (Transform child in obj.transform){
            SetLayerRecursively (child.gameObject, newLayer);
        }
    }
    public override void OnStartClient() {
        base.OnStartClient();
        string netID = GetComponent<NetworkIdentity>().netId.ToString();
        PlayerManager player = GetComponent<PlayerManager>();
        GameManager.RegisterPlayer(netID, player);
    }
    void AssignRemoteLayer() {
        gameObject.layer = LayerMask.NameToLayer(remoteLayerName);
    }
    void DisableComponents () {
        for (int i = 0; i < componentsToDisable.Length; i++) {
            componentsToDisable*.enabled = false;*

}
}
//when destroyed
void OnDisable () {
Destroy (playerUIInstance);
if (sceneCamera != null) {
sceneCamera.gameObject.SetActive(true);
}
GameManager.UnRegisterPlayer(transform.name);
}
}
And last but not least, the playerUI script:
using UnityEngine;
public class PlayerUI : MonoBehaviour {
[SerializeField]
RectTransform StaminaFill;
private PlayerController controller;
public void SetController (PlayerController _controller) {
controller = _controller;
}
void Start () {
controller = GetComponent();
}
void Update () {
SetStaminaAmount(controller.GetStaminaAmount());
}
void SetStaminaAmount (float _amount) {
StaminaFill.localScale = new Vector3 (1f, _amount, 1f);
}
}
So once again, the stamina calculates correct. It works. The prefabs are linked in the inspector correctly (the colored bar rect transform in the playerUI). Still, the bar doesn’t empty/ refill and I get this nullreference at the “SetStaminaAmount() in the PlayerUI Update()”, so I guess the script can’t find the right controller? Or it can’t receive the float amount from the public float in the controller OR the configure playerUI in the setup script doenst work… pff. I don’t get it! It should work right? I hope someone has the answer! Thanks in advance!

SetStaminaAmount(controller.GetStaminaAmount());
At this line, the only object that could be null is clearly the ‘controller’.

There are 2 ways in your code to set the variable ‘controller’. The first one is in PlayerUI, method Start() :

controller = GetComponent<PlayerController>();

And the second one in PlayerSetup, method Start() :

ui.SetController (GetComponent<PlayerController>());

This doesn’t sound good. I think that one of these two ways is doing a GetComponent<PlayerController> on a gameObject that actually doesn’t have the PlayerController attached.

If the PlayerSetup is on the gameObject with the PlayerController, so delete the PlayerUI’s Start().

If the PlayerUI is on the gameObject with the PlayerController, remove the line that does SetController in the PlayerSetup’s Start