2

I was looking around in the UnityEngine.UI source code. I was trying to understand how does the event system know what classes are implementing the IDragHandler interface, or any other eventsystem interface.

I got to a place where is a readonly objectbool> or something like this. But i didn't find where it was populated with data.

Does someone know how does the evetsystem know if a class is implementing an interface from the eventsystem? I found no place where the interface registers itself.

Marko Taht
  • 1,448
  • 1
  • 20
  • 40
  • 1
    @JamesThorpe wouldnt that be expencife if some objects are spawned at runtime, that have a script attached to that implement the interface? The Reflection script should run every update cycle then. – Marko Taht Nov 10 '17 at 14:54

2 Answers2

3

The GetComponent function is the answer. It implements the interface if it does not return null. If it returns null, the interface is not implemented.

For example:

The interface:

public interface IDrag { }

The script that implements it:

public class MyScript : MonoBehaviour, IDrag{ }

To check if the MyScript script implements the IDrag interface, use the GetComponent function.

IDrag idrag = gameObject.GetComponent<IDrag>();
if (idrag != null)
    Debug.Log("Implemeted IDrag");
else
    Debug.Log("DID NOT Implement IDrag");
Programmer
  • 121,791
  • 22
  • 236
  • 328
  • So basically it does this check on every object at every update cycle. Or this check i run on every new object once. – Marko Taht Nov 10 '17 at 17:07
  • It doesn't seem like every Update. This seems to happen only when it needs to call the function you implemented from the interface. In fact, it only needs to do `gameObject.GetComponent();` once. When it needs to call the function, it will check if the `idrag` variable is null before calling the function. – Programmer Nov 11 '17 at 03:23
  • So basically, when i start the game, it goes over all UI elements(since eventsystem is UI only), adds flags to all of the elements. And whenever it needs to call the methodit just needs to check the flag. And since it has to go over every UI element in every update anyways, there is basically no performance lost. – Marko Taht Nov 11 '17 at 17:03
  • Sorry I do not have the source code for this and it looks like the code to answer this part of question is not open to the public. They can store them in array in the beginning then check if null before calling them or they can use the flag you mentioned. That should work too. Now, as for the function to call (eg `OnBeginDrag`) that part is slow before it uses reflection to do so. The slowness should **not** matter and you won't notice it because it's just a UI event and this is only called when something happens. It's not called every frame. – Programmer Nov 11 '17 at 18:23
  • Oh ok... But lets say i want to do something similar outside of UI. Like some manager that manages some sort of things in happening. And i just have interface for the thing i want to happen. Would it be reasonable to make it as an interface and use reflections to find what implements it, or as an abstract class that register itself to the manager. – Marko Taht Nov 11 '17 at 19:35
  • Unity only used that method because they want to make it "easy". Unfortunately that method is only fine with UI only. It's slow when you use the-same method they use as event for your whole game. You seem to care about performance so I suggest you use `event` and `delegate`. See [this](https://unity3d.com/learn/tutorials/topics/scripting/events) for tutorial on that. [Here](https://stackoverflow.com/questions/42034245/unity-eventmanager-with-delegate-instead-of-unityevent) is a complete one I made – Programmer Nov 11 '17 at 19:56
1

The ExecuteEvents class contains a method for checking if a GameObject can handle a specific UI event (IEventSystemHandler of type T), e.g.:

bool handlesDrag = ExecuteEvents.CanHandleEvent<IDragHandler>(gameObject);

This returns true iff gameObject implements the IDragHandler interface.

Documentation at:

https://docs.unity3d.com/ScriptReference/EventSystems.ExecuteEvents.CanHandleEvent.html

Reinier
  • 88
  • 6