0
\$\begingroup\$

I am learning about Actions/Events in Unity and just built a system around them which works. However, it seems I just got lucky and I'm not sure why.

Roughly, my class in a simple illustrative form (skipping the deeper logic and just showing one Action) looks like this:

public class ClickableElement: VisualElement {
    public event Action setClickedDownAppearance;

    public ClickableElement() {
        setClickedDownAppearance += delegate { }; //EMPTY DELEGATE LINE NEEDED FOR SCRIPT TO WORK
    }

    private void updateClickState() {
        if (mouseDown) {
            setClickedDownAppearance(); //line that throws the error without the above line present
        }
    }
}

Then when I create my element it would be something like:

ClickableElement testElement = new ClickableElement();
testElement.setClickedDownAppearance += delegate { testElement.style.backgroundColor = new StyleColor(Color.cyan); };

The idea is that I can set the parameters for what it should look like or what functions it should run on clicking when I generate the element.

As I said it works fine just like that.

What I don't understand is if I get rid of the line tagged EMPTY DELEGATE LINE NEEDED FOR SCRIPT TO WORK the whole thing breaks. It says Object reference not set to an instance of an object when I try to run setClickedDownAppearance();.

I actually just got completely lucky in building this because I had some simple debug code added to the blank delegates in the constructor. Without that none of this would have worked. But I'm not sure what the issue is since I barely understand these "event Action" things enough to use them.

If I got rid of the line setClickedDownAppearance += delegate { }; is there some way I could write public event Action setClickedDownAppearance; so that it still "exists" and can function?

Thanks for any clarification.

\$\endgroup\$
3
  • \$\begingroup\$ Isn't it just that the Event is not initialized if you miss the line? You could do as well a check if it has an action assigned before calling it. Same happens if you call a delegate or unity event without a backing function \$\endgroup\$
    – Zibelas
    Jan 1, 2022 at 11:24
  • \$\begingroup\$ If you are wondering if that is okay to do it like this - yes. It's pretty standard, yes you are going to have an empty delegate there each time it's invoked, so a little performance overhead, but it's so low I don't know if I would ever notice it in my code at least. public event Action<float> OnVolumeChange = delegate { }; example. You can also do ? check. More on performance here stackoverflow.com/questions/170907/… . \$\endgroup\$ Jan 2, 2022 at 3:43
  • \$\begingroup\$ Thank you Candid Moon _Max. That syntax was exactly what I was looking for so I don't have to do it in the constructor. I will follow that method. Good to know it is considered a normal approach. \$\endgroup\$
    – mike
    Jan 2, 2022 at 11:29

1 Answer 1

1
\$\begingroup\$

Normally you would subscribe an Action with:

action += method;

and then when you want to call it:

action?.Invoke();

so the question mark ensures that it will return and not throw an error if nothing is subscribed.

\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .