Event Handlers in GameObject Script Controllers and External Libraires

Ok to start with sorry for the title. I really had no idea what to call this. I have a problem with how I am interpreting and implementing an application I am developing.

I am doing my bachelor thesis for media technologies. So I teamed up with 2 guys who are developing a hand-based interface for motion sensors. Right now they are using the Leap Motion to develop there interface. What I am exploring is different screen based interpretations of their touchless gesture based interface.

Now basically the setup is I have 2 hands that are grasping a ball. The ball is split into 2 parts and so essentially I have 4 GameObjects. Each gameobject has a controller. This controller handles their respective animations. They all look something more or less like this:

public class Hand_L_Controller : MonoBehaviour
{
   
        Animator anim;   
    
        int Thumb     = Animator.StringToHash("Thumb");
        int Pointer    = Animator.StringToHash("Pointer");
        int Middle     = Animator.StringToHash("Middle");
        int Ring        = Animator.StringToHash("Ring");
        int Pinky      = Animator.StringToHash("Pinky");

	void Start () {
            anim = GetComponent<Animator>();
	}
	
	
	void Update () {
            if (Input.GetKeyDown(KeyCode.J))
                anim.SetBool(Thumb, true);

            if (Input.GetKeyDown(KeyCode.K))
                anim.SetBool(Pointer, true);

           // etc....
	}
}

This works great if Im just using the keyboard. BUT! I have an API these 2 guys have developed for me to use to be able to interpret when a user presses a finger for example through their application that interprets the leap motion data. Imagine your holding a ball in the air and when you tap your fingers different keys are tapped according to what finger you tap with. So I have a class that I call APIListener and this derives from there own self authored Listener Class. All this class does is override a method called OnFrameUpdate(Data data):

public class APIListener : TheirListener{

    public override bool OnFrameUpdate(Data data)
    {
        // do stuff
    }

}

In this method I can read the data object and it will have booleans for example as to whether the ring finger was recorded as tapped or etc…

so for example:

public override bool OnFrameUpdate(Data data)
    {
        if (data != null)
            {
                 if(data.Hand.LeftFinger.isTapped)
                 {
                             //do something
                 }
            }
    }

In order to start up the entire API I instantiate their controller. So in my Hand_L_Controller class I could say

TheExternalController EC = new ExternalController(new APIListener());  //(I need to pass my derived class to their controller).
EC.init();

Ok. My problem is this. I really have no access to that overriden method anymore aside from directly writing my logic in that class. But how could I access 4 different Animator objects and put them all in that class and have them all listening for booleans from the Data object? Or I was thinking maybe I could setup some sort of EventHandler, but again I’m not really sure where I would do that. I would want my Hand_L_Controller and Hand_R_Controller classes to be able to either receive data from the OnFrameUpdate method or at the very least know when it is being fired, but is that even possible with the way I have it setup?

I am basically looking for a bit of guidance or advice. Is this a problem I can solve? Or do I need to get the guys to develop their API for me a bit differently? Or is the way I am setting it up awkward and wrong? If so how would I change it?

What actually calls “OnFrameUpdate”?

Well that’s the thing. I don’t know what calls it because its part of the 2 guys collaborating with’s program. I know that essentially it gets called every time the LeapMotion gets new data. So somewhere in their program they are most likely using the leap motion SDK to read new hand movement and packet it into an object : in this case Data data, that I can receive in that method I override and do my logic with.

Why do the hand representations in your scene have to receive the events directly?

If I were doing this, I’d have a single object (not necessarily even a MonoBehaviour) that was responsible for all listening and low-level interpretation of the data received from the external library. I’d then have that object broadcast messages in its application to notify local objects of changes they might care about.

So, that class you have to extend and override a method in wouldn’t be performing the logic itself. It’d just be adapting the data to a format useful to whatever I was doing, then informing the rest of the app that there’s new data. Don’t try and do everything in one place.

Note that classes in Unity do not have to be MonoBehaviours. You have Mono/.NET at your disposal, don’t throw out your software design knowledge just because the default code template assumes you’re attaching the class to a GameObject! You could easily enough have one MonoBehaviour that’s responsible for spinning up some non-MonoBehaviour classes when a scene is opened (which could be extended to be a life-cycle controller for that stuff if relevant) and then have your other MonoBehaviours listen for events generated by those. Or… well, anything you want, really. It might be helpful to consider a MonoBehaviour as an adapter into your scene.

On a different note, why have “Hand_L_Controller” and “Hand_R_Controller” rather than just two instances of “Hand_Controller” configured differently? Unity makes heavy use of component based architecture, and one of the biggest benefits of that is the ability to re-use components if they’re designed effectively. Can the left and right hands be different configurations of the same thing? (This may be easier if that class is broken down into smaller components used in different combinations. “Composition is better than inheritance”, and all that.)

Yeah, after reading your reply I definitely woke up a little bit. Its amazing how narrow sited one can get sometimes with pre conceived rules.

I definitely did not want to do everything in a single place, I just though I might end up having to. I also thought, yeah!? why do I need to have two Hand controllers. I can just as well have 1 that like you said behaves differently depending on the configuration. I now have a main controller for the app where I pass a delegate to the API listener that brings the data over into my main controller. Now because I also have just one hand controller class that is assigned to each hand I can affect each hand depending on the data as I see fit ^^!!! I also implemented this for the 2 hemispheres of my circle.

Thank you!