UnityEvent and private methods

So, I’ve got a UnityEvent with parameters…

[System.Serializable]
public class BlahEvent : UnityEngine.Events.UnityEvent<string> { }

...

public BlahEvent OnBlahHappened;

This shows up in my Inspector as expected.

Last week, I set up a bunch of these in the Inspector to point at private methods in scripts attached to a parent GameObject. So I had methods like this and in the Inspector I could hook them up to UnityEvents defined as above:

private void BlahHappened(string value) {
       OnEndEdit.Invoke(this, value);
     }

This week I’ve gone back to the same project. All of the events I hooked up last week still work, but I can no longer hook new events up to private methods.

If I make the same methods public they work as expected. But as long as they’re private, when I try to add them to the event in the Inspector they just don’t appear in the relevant list. Also, looking at the ones I hooked up last week, they’re still hooked up and they still work, but if I try and re-hook them their relevant private methods don’t show in the listings either.

I checked the documentation, and it’s unclear whether private methods are meant to work in the first place. The only reason these methods exist is specifically to be invoked from the UnityEvent, so I’d like them to be private if possible. But if UnityEvent is only meant to access public methods in the first place - which makes sense - then I’ll update the methods accordingly.

My confusion arises from the fact that I could do this last week, but I can’t do it now, even on the same objects where I did it last week and I am sure nothing has changed.

Any ideas?

This kind of thing is beyond me, as I’ve never worked with UnityEvents, but I did have a thought about it. Have you checked to see if it’s some sort of internal caching issue? In other words, can you try to create new events attached to private methods in this same way, save, and restart Unity to see if it then updates the list properly? In my experience when time is the only factor in something working or not working, it’s because of some sort of cache/update problem…

Did you update Unity in the last week?

If you did, what version were you on before, and what version are you on now?

UnityEvent connects to methods via reflection, and when you reflect methods you can reflect them as only public methods, or as public and nonpublic. Unity maybe altered the code behind this reflection and changed the BindingFlags to only support public methods. If you did update, and you know which version you left, and which version you went to, and you check the version release notes, it might say something about that.

I don’t know if they actually changed this behaviour as I use my own event system that I wrote a long while before UnityEvent came out… but I do it in a very similar way, and the BindingFlags when reflecting methods is the key to this thing.

[edit]
I will say though that looking at the decompiled UnityEditor.dll for the UnityEventDrawer, and the way it grabs the methods for the drop down only pulls the public methods. That is for Unity 4.6.7f1 (the version I’m currently on).

I can’t verify what it was in the past. Don’t have any older versions laying around to check.

If I mark them as public they appear as soon as Unity re-compiles the scripts. If I make them private again they disappear as soon as the script is recompiled.

This has crossed my mind. I have done an update recently. I’m reasonably sure it was before I started work on this, but could be mistaken.

My best guess at this stage is that I actually hooked them up while they were public, then looked at the wrong thing when checking if I could use private methods (I have a comment in my code noting that I did check this), then updated them all to be private. Now that I’ve come along to hook up a new one that was private in the first place it doesn’t show up in the list.

To be honest I wouldn’t expect those lists to show private methods anyway, at least not in normal circumstances. It wouldn’t make much sense to expose every internal method to be called willy nilly.

They were only meant to work with public events. I’m picking it was a bug fix you got in the update.

I’d imagine they still work because when using reflection to get a list in the inspector its most efficient to separate the inspector from the actual event. The inspector has code to reflect and iterate over every method to find the target method. But at runtime you only need to look for the target method.

To get it back to its old behaviour you would have to update the property drawer for UnityEvent to include private binding flags. I wouldn’t have a clue how to go about this.

Just seems stupid to bind private methods into events. Like why bother with encapsulation, if your going to let external things access the private methods anyways.

This only makes sense for C# events and delegates, or when using AddListener() on a UnityEvent since in this case you are reversing responsibility and having a class add its own methods as event callbacks.

1 Like