Unity Events behave different from different methods

Hi there.
I can’t figure out a thing reguarging unity events.
Basically, i have a script with some methods, in two of these methods i call an event to executing a method of another script.

here’s the code:
Here’s where i initiate the event:
public UnityEvent<Pose, TrackingState, int> OnAnchorPoseUpdate;

Here’s one method that calls the event:

public void SaveData()
    {
        if (data == null || path == "")
            return;
        Debug.Log("data value: " + data.Count);
        string json = JsonHelper.ToJson<AnchorData>(data);
        if (json == null)
            return;
        Debug.Log("Json value: " + json);
        File.WriteAllText(path, json);
        Debug.Log("Saved in " + path);
        OnDebugSent.Invoke(string.Format("Sending last added anchor: UUID {0}, UDK {1}, worlAnchor UUID {2}, worldAnchor UDK{3}", lastAddedAnchor.UUID, lastAddedAnchor.UserDefinedKey, lastAddedAnchor.worldAnchor.UUID, lastAddedAnchor.worldAnchor.UserDefinedKey));
        CallPoseUpdate(lastAddedAnchor.worldAnchor, lastAddedAnchor.markerID);
    }

And finally the other method that calls the event:

public IEnumerator LoadAnchor(int  markerID, AnchorData anchor)
    {
        
        if (anchor == null)
            yield break;
        Debug.Log("loading anchor");
        localMap.Load(anchor.UUID, anchor.UserDefinedKey);
#if !UNITY_EDITOR
        int counter = 0;
        do
        {
            OnDebugSent.Invoke("Trying to get a tracking nrWorldancor: " + counter++);
            yield return new WaitForSeconds(0.6f);
            anchor.worldAnchor = GetWorldAnchor(anchor.UUID);
        } while (anchor.worldAnchor.CurrentTrackingState != TrackingState.Tracking && counter <= 5);
#elif UNITY_EDITOR
        yield return new WaitForSeconds(0.4f);
        anchor.worldAnchor = GetWorldAnchor(anchor.UUID);
#endif
        anchor.worldAnchor.gameObject.name = "NRAnchor_" + markerID;
        loadedAnchors.Add(anchor.markerID);
        CallPoseUpdate(anchor.worldAnchor, markerID);
    }

The CallPoseUpdate method is the following:

if(null == anchor)
        {
            OnDebugSent.Invoke("anchor is null");
            return;
        }
        if(null == anchor.transform)
        {
            Debug.Log("transform is null");
            return;
        }
        Pose newPose = new Pose(anchor.transform.position, anchor.transform.rotation);
        if(newPose == null)
        {
            Debug.Log("new pose is null");
        }
        OnDebugSent.Invoke(string.Format("Calling poseUpdate with thees values: newPose {0}, ancor.CurrentTrackingState {1}", newPose, anchor.CurrentTrackingState));
        OnAnchorPoseUpdate.Invoke(newPose, anchor.CurrentTrackingState, markerID);

the fisrt method, SaveData(), gets called by another script, the second, LoadAnchor(int, AnchorData), is called by another method in the same script.

Here comes the part that confuses me: for some reason, when i try calling “CallPoseUpdate” from the SaveData() method, it won’t work, i even checked if some paramethers were null in debug mode but everything had a value, the only thing missing was the listener for some reason.
However, when called by LoadAnchor() method, then it will work.
I don’t know why, could you please explain?
Ask me whatever you didn’t understand. Thanks!!

Theres two possibilities. Either the two methods are calling different instances, or the event is getting invoked before/after your listeners to the event had added/removed themselves.

Note that one is called in a coroutine after a few frames have passed, likely giving other code time to bind with the event

Hey, thanks for the reply @JoshuaMcKenzie, could you please explain a bit how to check if

the event is getting invoked before/after your listeners to the event had added/removed themselves

A thing i forgot to mention is that also the

OnDebugSent.Invoke(string.Format("Sending last added anchor: UUID {0}, UDK {1}, worlAnchor UUID {2}, worldAnchor UDK{3}", lastAddedAnchor.UUID, lastAddedAnchor.UserDefinedKey, lastAddedAnchor.worldAnchor.UUID, lastAddedAnchor.worldAnchor.UserDefinedKey));
won’t get called at all.
Is there a problem with doing an event call from when passing from a class to the other and then returning back in the other class?

If that helps, here’s the method that calls the “save data” method:

private void CheckQuality()
    {
        Debug.Log("Checking Quality");
        if (qualityIndicator == null)
            return;
        if (qualityIndicator.CountOfGoodBars >= goodResult)
        {
            if (anchor == null)
            {
                print("anchor item not found");
                return;
            }
            Debug.Log("saving anchor item");
            container.SaveData();
            anchor.Save();
            CancelInvoke("CheckQuality");
            return;
        }
    }

that “container.SaveData()” is our method, and the “anchor.Save()” saves some data do the disk.

Now that i think about it i had some “similar issues” with “data” and “lastAddedAnchor” in the SaveData() method, where i had to make them static or they would lose their value, should i make the unityEvents also static?

Thanks

Events are simply a place where when something happens in one class another class should do something. it allows Class A (typically known as the publisher) to fire functions on Class B (the subscriber) without class A needing to explicitly know anything about class B. Class A controls “when” something happens, Class B controls “what” to do when that happens.

The thing is class B needs to be subscribed at the time class A’s event is invoke. if class A invokes its event before class B adds its listener class B won’t run its code. if that action in particular are hooked up via the inspector you have nothing to worry about as that is implicity added to the event when the class is deserialized, before an awake is called. but if you are adding removing listeners programmatically you will need to pay attention to when you are adding/removing listeners and when you are invoking the event.

That said, based on what you’ve added, if the debug is also missing you should try using breakpoints. this provides great insight for bugs that can be inspected step-by-step.

  1. Add a breakpoint on the line you are expecting to call (click on the highlighted column to the left of the line number to place a red dot, that is a breakpoint)
  2. in visual studio you should see a green play button that says “Attach to Unity” press that to enter debugging mode.
  3. Run the game in-editor and get to the point where you expect the game to run the buggy code.

if the breakpoint is hit the game should freeze and you will be able to go step by step in Visual Studio to see what the code is doing. you can hover over variables to see their values at each line of code and you can use the “step into”, “step over” commands to walk through the code. step into will follow into whatever class/function is on the line so that you can go step by step in those places, while step over goes to the next line in the current scope. “step out” does the opposite and tries to go through the rest of the scope and get back to the previous scope. the debugging will stop if it hits an exception along the way.

Take note that while debugging unity’s process is paused, this can cause third party processes and services to break/shutdown if you are using them in unity (for example connection to an online multiplayer service can be closed as the server lost signal to your game’s process)

Thank you @JoshuaMcKenzie for your reply.
I’ve already tried running unity in debug mode and i found that every field had a value, however the call had lo listeners.
I tried setting the events as static variables an it works, but it confuses me a little.
I have hooked the actions in the unity inspector, so there shouldn’t be ANY issues about a listener not being present.
I thought that, since i temporarly leave the “script A”, whitch contains the event variables, to do some stuff in a “script B” to then come back in “script A” to attempt an event invoke, in the meantime the “garbage collector” or whatever noticed that nobody was using “script A” anymore and trhew all the variables in the trash, but i don’t think it should happen as it’s referenced in the inspector.
I don’t know, I’m not an expert programmer, just a student, so i could be wrong about that.
Sorry for my english in case i wrote some wierd words.

Thank you for the patience