Search code examples
c#unity-game-enginevirtual-realityleap-motion

Unity-LeapMotion: How to setup an event with an attached InteractionBehavior script with c#


for interacting with an object in Unity via LeapMotion controller you need to attach the "IneractionBehavior" script. With this script you can create new interaction events with the unity GUI.

What i want is to generate a couple of GameObjects with an attached InteractionBehavior script and i want to add these types of events via C# code.

For example i want to generate automaticaly an object with a attached InteractionBehavior script and want to define per code that this object turns to red by BeginContact.

I use: - Unityversion 2019.1.10 - LeapMotion Core Asset v4.4.0 - LeapMotion InteractionEngine v1.2.0 - HTC Vive Pro

If it is possible i want to know how i can add an interactionevent to an attached InteractionBehavior script with C#


Solution

  • This is the implementation of BeginContact in the InteractionBehaviour :

    public void BeginContact(List<InteractionController> controllers) 
    {
        foreach (var controller in controllers) 
        {
            _contactingControllers.Add(controller);
    
            OnPerControllerContactBegin(controller);
        }
    
        if (_contactingControllers.Count == controllers.Count) 
        {
            OnContactBegin();
        }
    }
    

    as you can see the according actions called are

    public Action OnContactBegin;
    public Action<InteractionController> OnPerControllerContactBegin;
    

    So depending on your needs either

    Directly add callbacks via script

    e.g. using

    private void Awake()
    {
        var interactionBehaviour= objectReference.GetComponent<InteractionBehaviour>();
    
        // either as Lambda Expression
        interactionBehaviour.OnContactBegin += () =>
            {
                // do something here
            };
    
        // or with a method
        // use this if you also want to be able to remove callbacks later!
        // it is always save to remove a callback before adding it
        // even if it's not there yet. Makes sure it is only added exactly once
        interactionBehaviour.OnContactBegin -= DoSomething;
        interactionBehaviour.OnContactBegin += DoSomething;
    }
    
    // make sure to always remove any callbacks as soon as possible or when they are not needed anymore
    private void OnDestroy()
    {
        interactionBehaviour.OnContactBegin -= DoSomething;
    }
    
    
    private void DoSomething()
    {
        // do something here e.g. turn red
        // for efficiency you would ofcourse move the GetComponent
        // call to Awake as well. Just wanted to keep the example clean
        GetComponent<Renderer>().material.color = Color.red;
    }
    

    Or make it more general

    Inherit from the script and customize it with UnityEvents which bring their own Inspector visiable interface (exactly like the Button.onClick event).

    Theoretically you could add UnityEvent for every single Action available .. I will just do it for the two above.

    [Serializeable]
    public class InteractionControllerEvent : UnityEvent<InteractionController> { }
    
    public class ExtendedInteractionBehaviour : InteractionBehaviour
    {
        public UnityEvent OnContactBeginEvent;
        public InteractionControllerEvent OnPerControllerContactBegin;
    
        // and just as before add those as callbacks to the actions
        private void Awake()
        {
            OnContactBegin -= OnContactBeginInvokeEvent;
            OnContactBegin += OnContactBeginInvokeEvent;
    
            OnPerControllerContactBegin -= OnPerControllerContactBeginInvokeEvent;
            OnPerControllerContactBegin += OnPerControllerContactBeginInvokeEvent;
        }
    
        private void OnDestroy()
        {
            OnContactBegin -= OnContactBeginInvokeEvent;
            OnPerControllerContactBegin -= OnPerControllerContactBeginInvokeEvent;
        }
    
        private void OnContactBeginInvokeEvent()
        {
            OnContactBeginEvent?.Invoke();
        }
    
        private void OnPerControllerContactBeginInvokeEvent(InteractionController controller)
        {
            OnPerControllerContactBegin?.Invoke(controller);
        }
    }
    

    Now you could simply reference GameObjects and their components & methods via the Inspector as you probably know it from the mentioned UI.Button.onClick event (it also is an UnityEvent).

    Especially the InteractionControllerEvent is an example that allows to be called with an dynamic parameter, meaning the according InteractionController reference can be passed on to a referenced method taking a InteractionController as paramter.