[SOLVED]Null object reference in an array of function pointer

Hello I’m working on an AI and I have an error and can’t figure out why.

The AI is a state machine, I’ve put all the states in an enum and linked them to the related function thanks to an array of function pointer. The problem is I get an error message “Object reference not set to an instance of an object” pointing on the line 19. I don’t know what’s going on, the AI is working as expected and after 2 or 3 minutes I get this error and I don’t know why.

public enum State {
        ATTENTE_ENGIN,
//[...]
        LEVAGE_CHARGE
    };
    private delegate void Del ();
    private Del[] currentState = new Del[39];
    public State state;

void Start () {
        state = State.ATTENTE_ENGIN;
        currentState[(int)State.ATTENTE_ENGIN] = attenteEngin;
//[...]
        currentState[(int)State.LEVAGE_CHARGE] = levageCharge;
    }
   
    // Update is called once per frame
    void Update () {
        currentState[(int)state]();
    }

There is no way to say with only the code you provided. Specifically, there may be more code modifying the “currentState” array.

  1. that entry in the array doesn’t have a value. Did you initialize the array to its capacity?

  2. you can always check if the reference exists before calling it

  3. Why do you have an array of delegates? Why not set the current delegate on state change?

public class MyAI : MonoBehaviour
{

    private System.Action _currentState; //note, a delegate of the shape you described already exists
  
    private void Start()
    {
        _currentState = this.Attente_Engin;
    }
  
    private void Update()
    {
        if(_currentState != null) _currentState();
    }
  
    private void Attente_Engin()
    {
        //do attente engin
    }
  
    private void Levage_Charge()
    {
        //do levage charge
    }
  
}
1 Like

On a side note: if you’re still using the enum you should probably use the enum size to initialize the array. Like:

private Del[] currentState = new Del[Enum.GetValues( typeof( State ) ).Length];

First, thanks for your answers.

The CurrentState array is NEVER modified, only the attribute “state” is.

  1. I’m not sure what you are talking about, do you ask if I initialized the array capacity or if I filled every entry of the array ?

  2. Because that would only hide the problem not resolve it.

  3. I didn’t thought my code this way, I will do this if I can’t resolve the problem but I want to try to resolve it first.

I used to do that but removed it when I started to have this bug.

PS : sorry for my broken english

Then you are accessing an empty slot. Try debug-printing the index variable that you use to access that slot.

I can’t see how it could happen. Each one of the 39 slots are filled, to be sure I copy/pasted the enum in the Start() function and started from this to write the part where I initialize the array.

Also, the attribute state is public so I can check if I’m at the correct step at any given time while running the simulation. The last times it happened it didn’t seem related to any particular state, I will double check it the next time it happen. The thing is it look like it’s resolved since it doesn’t happen anymore but I changed nothing, this bother me a lot.

Yes. But what if your code trys to access [39] of the array? :slight_smile:

Sounds like a typical indexing problem. Array has 39 elements, last indexable element is 38.

The main issue is that you are not sharing the complete code. What could happen is that currentState becomes null which would lead to that kind of error message as well. We can’t have an actual look at your code, but everyone has to blindly guess.

Is it possible that the object providing the delegate has been destroyed?

Then it will be a very different exception.

Oh. It’s “Index out of range”. Of course. Sorry.:confused:

I don’t think I can provide the complete code since it’s a business related project, I would do it if it was a personal project. But I provided everything who is related to the state and state change.

I’m not sure but shouldn’t the script stop working if the linked object is destroyed ? Since the script is a component of the object who is destroyed.

EDIT : got it again after one hour of idling on the same state … “NullReferenceException: Object reference not set to an instance of an object TestAI.Update () (***TestAI.cs:130)”

I’m now sure that the bug isn’t related to any particular state,

It is not a big deal if you simplify the code as long as you can still reproduce the issue. However, with the code you are actually showing, you leave for too much open space, such that people here need to guess.

It could be that currentState is null. It could be that a delegate is null. It could be that the delegate tries to access an object that was destroyed.

Splitting the code up into two lines for testing purposes might help to isolate the issue, however, that is exactly the part we can’t see.

1 Like

So you’re saying that the AI script and the script providing the delegates is on the same gameObject? If so, yes, destroyig the object will destroy the AI script and not cause any issue. Is there anything in your code that will destroy not the gameObject but rather just the component providing the delegates ?

I reduced my script as much as possible for testing purposes to isolate the issue. It look like the error happen when I edit the script while the simulation is still running.

Not such a big deal if it’s confirmed …

Oh god I lost 2 hours for this

Does it work now? If so, you shouldn’t consider time spent learning as lost time.

I fixed nothing and didn’t learned much more, just that it’s not ok to edit a script on MonoDevelop while Unity is running it, because it could run an random NullReferenceException if you use a array (and/or ?) delegates in this script, but I still don’t know why.