NullReferenceException problem

Hello,

I have several scripts attached to game objects, and each game object has also a Particle System
(as prefab) attached to it via serialized field visible in inspector.

In the scripts, a ThrusterController class is instantiated with new. One version is working, but a slightly
different one leads to a NullReferenceException. Would be nice I someone could explain it why that is,
I am new to Unity. Thanks.

Working class implemtation (of a script attached to a game object):

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

public class HorizontalRearThrusterController : MonoBehaviour
{
    [SerializeField] ThrusterController controller = new ThrusterController();
    private KeyCode keyCode;

    private void Awake()
    {
      
    }

    void Start()
    {
        controller.ThrusterOrientation = 1;
        controller.ParticleEmitterOffsetOnThrustReversal = 0f;
        controller.IncThrustKey = KeyCode.E;
        controller.DecThrustKey = KeyCode.R;
        var main = controller.ThrusterParticle.main;
        main.startLifetimeMultiplier = 2f;
        main.simulationSpeed = 0;
        controller.ThrusterParticle.Play()
    }

    void Update()
    {
        controller.ProcessCommand(gameObject);
    }
}

Class implentation with NullReferenecException on highlighted line:

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

public class HorizontalRearThrusterController : MonoBehaviour
{
    [SerializeField] ThrusterController controller = null;
    private KeyCode keyCode;

    private void Awake()
    {
      controller = new ThrusterController(),
    }

    void Start()
    {
        controller.ThrusterOrientation = 1;
        controller.ParticleEmitterOffsetOnThrustReversal = 0f;
        controller.IncThrustKey = KeyCode.E;
        controller.DecThrustKey = KeyCode.R;
       [COLOR=#ff0000] var main = controller.ThrusterParticle.main;[/COLOR]
        main.startLifetimeMultiplier = 2f;
        main.simulationSpeed = 0;
      [COLOR=#ff0000]  controller.ThrusterParticle.Play()[/COLOR]
    }

    void Update()
    {
        controller.ProcessCommand(gameObject);
    }
}

Here the ThrusterControllerClass:

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

[System.Serializable]
public class ThrusterController
{
    [SerializeField]  ParticleSystem thrusterParticle;
    private  int thrust=0;
    private int thrustDirection = -1;
    private int thrustMin = -10;
    private int thrustMax = 10;
    private float particleEmitterOffsetOnThrustReversal = 0;
    private int thrusterOrientation = 0;
    private KeyCode incThrustKey;
    private KeyCode decThrustKey;

    public ThrusterController()
    {
       
    }

    public ParticleSystem ThrusterParticle
    {
        get { return thrusterParticle;}
    }

    public int Thrust
    {
        set { thrust = value; }
        get { return thrust; }
    }

    public KeyCode IncThrustKey
    {
        set { incThrustKey = value; }
        get { return incThrustKey; }
    }

    public KeyCode DecThrustKey
    {
        set { decThrustKey = value; }
        get { return decThrustKey; }
    }

    public int ThrustMin
    {
        set { thrustMin= value; }
        get { return thrustMin; }
    }

    public int ThrustMax
    {
        set { thrustMax = value; }
        get { return thrustMax; }
    }

    public int ThrusterOrientation
    {
        set { thrusterOrientation = value; }
    }


    public void SetThrusterParticleSpeed()
    {
        thrusterParticle.playbackSpeed = Mathf.Abs(thrust) / 10.0f;
        if (thrust == 0) thrusterParticle.Clear();
    }

   
    public void RelocateVerticalThruster(GameObject thruster, int thrustDirection, float offset)
    {
        thruster.transform.Rotate(thrustDirection * 180, 0, 0);
        float move = thruster.transform.localPosition.y;
        float _x= thruster.transform.localPosition.x;
        float _z= thruster.transform.localPosition.z;
        move += offset*thrustDirection;
        thruster.transform.localPosition = new Vector3(_x, move, _z);
    }


    public void RelocateHorizontalThruster(GameObject thruster, int thrustDirection, float offset)
    {
        thruster.transform.Rotate(thrustDirection * 180, 0, 0);
        float move = thruster.transform.localPosition.z;
        float _x = thruster.transform.localPosition.x;
        float _y = thruster.transform.localPosition.y;
        move -= offset * thrustDirection;
        thruster.transform.localPosition = new Vector3(_x, _y, move);
    }

    public void ProcessCommand(GameObject thruster)
    {
        if (Input.GetKeyDown(IncThrustKey))
        {
            Debug.Log(IncThrustKey);
            if (Thrust < ThrustMax)
            {
                Thrust++;
                SetThrusterParticleSpeed();
            }

            if (thrustDirection == 1 && Thrust > 0)
            {
                thrustDirection = -1;
                if(thrusterOrientation==0) RelocateVerticalThruster(thruster, thrustDirection, particleEmitterOffsetOnThrustReversal);
                else RelocateHorizontalThruster(thruster, thrustDirection, particleEmitterOffsetOnThrustReversal);
            }

        }
        else if (Input.GetKeyDown(DecThrustKey))
        {
            if (Thrust > ThrustMin)
            {
                Thrust--;
                SetThrusterParticleSpeed();
            }

            if (thrustDirection == -1 && Thrust < 0)
            {
                thrustDirection = 1;
                if (thrusterOrientation == 0) RelocateVerticalThruster(thruster, thrustDirection, particleEmitterOffsetOnThrustReversal);
                else RelocateHorizontalThruster(thruster, thrustDirection, particleEmitterOffsetOnThrustReversal);
            }
        }
    }

    public float ParticleEmitterOffsetOnThrustReversal
    {
        set { particleEmitterOffsetOnThrustReversal = value; }
    }
       
}

This is just a C# error telling you that you are accessing a reference that isn’t referring to any object so it’s NULL. It’s by far the most common error posted here. So much so that we have a sticky post in this forum here: https://forum.unity.com/threads/how-to-fix-a-nullreferenceexception-error.1230297/

The “highlighting” isn’t working above and isn’t useful. Best to state which lines and which field/property. A very quick look would indicate that it’s not the “controller” field as you initialize it but instead it’s likely it’s telling you it’s the “thrusterParticle” field. Does it say that? Where do you initialize that?

If it isn’t that then only you can debug it as you have the project. Showing the code doesn’t show the configuration so it’s up to you. Use “Debug.Log()” and check what’s NULL. Better still, attach the debugger and look for yourself, that’s super easy to do: Unity - Manual: Debug C# code in Unity

Hello,
Thank you for the hints.

It is the thrusterParticle field:

NullReferenceException: Object reference not set to an instance of an object
HorizontalFrontThrusterController.Start () (at Assets/Scripts/Thruster/HorizontalFrontThrusterController.cs:26)

This corresponds to this codeline in Start():

var main = controller.ThrusterParticle.main

Seems this not a good idea: [SerializeField] ThrusterController controller = null;

It will set the the Thruster Particle field back to “None” and the reference is lost,
and controller = new ThrusterController() in the Awake() function will not do anything about it.
Could that be correct with my conclusion, or is more to consider?

8431169--1116407--upload_2022-9-11_3-55-34.png

You show a HorizontalFrontThrustController, and it has a ThrustController in it with the ParticleSystem reference.

You should be dragging the ParticleSystem. instance into the inspector for the ThrustController.

And besides, are you sure you don’t have another one of these things in scene that isn’t set up? Search for it by type in the search bar.

Because… yes, you guessed it, the answer is always the same for nullref. :slight_smile:

How to fix a NullReferenceException error

https://forum.unity.com/threads/how-to-fix-a-nullreferenceexception-error.1230297/

Three steps to success:

  • Identify what is null
  • Identify why it is null
  • Fix that

This is working, first line of class HorizontalRearThrusterController:

[SerializeField] ThrusterController controller= new ThrusterController().

It just does not work, when setting the reference in the constructor of that class

I meant to say in the Awake() function, not in the constructor…

Note you can Edit posts to correct typing mistakes.

I’m not even sure what is going on here.

You’re marking the thruster field for serialization so it shows in the editor, and gets serialized.

Then you’re new-ing a fresh non-MonoBehaviour thruster script up at Awake

As part of that you expect it to be the same one and have the ParticleSystem you might have set in the inspector.

I assure you the class you create with a new won’t have that ParticleSystem defined. I also have no idea where you intend to set that. It won’t be in the inspector because obviously when you run, Awake() will happily wipe it out with the new call.

Serialized properties in Unity are initialized as a cascade of possible values, each subsequent value (if present) overwriting the previous value:

  • what the class constructor makes (either default(T) or else field initializers)

  • what is saved with the prefab

  • what is saved with the prefab override(s)/variant(s)

  • what is saved in the scene and not applied to the prefab

  • what is changed in Awake(), Start(), or even later etc.

Make sure you only initialize things at ONE of the above levels, or if necessary, at levels that you specifically understand in your use case. Otherwise errors will seem very mysterious.

Field initializers versus using Reset() function and Unity serialization:

This might also be useful to you:

Here is some timing diagram help:

Thank you for the links, will go through it.

Its clear now, probably I did not see the forest because of too many trees…

This just works:

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

public class HorizontalFrontThrusterController : MonoBehaviour
{
    [SerializeField] ThrusterController controller;
    private KeyCode keyCode;
   
    private void Awake()
    {
      
    }

    void Start()
    {

        controller.ThrusterOrientation = 1;
        controller.ParticleEmitterOffsetOnThrustReversal = 1.8f;
        controller.IncThrustKey = KeyCode.Q;
        controller.DecThrustKey = KeyCode.W;
        var main = controller.ThrusterParticle.main;
        main.startLifetimeMultiplier = 2f;
        main.simulationSpeed = 0;
        controller.ThrusterParticle.Play();
    }

    void Update()
    {
        controller.ProcessCommand(gameObject);
    }
}
1 Like