Hello everyone.

The Mixed Reality Forums here are no longer being used or maintained.

There are a few other places we would like to direct you to for support, both from Microsoft and from the community.

The first way we want to connect with you is our mixed reality developer program, which you can sign up for at https://aka.ms/IWantMR.

For technical questions, please use Stack Overflow, and tag your questions using either hololens or windows-mixed-reality.

If you want to join in discussions, please do so in the HoloDevelopers Slack, which you can join by going to https://aka.ms/holodevelopers, or in our Microsoft Tech Communities forums at https://techcommunity.microsoft.com/t5/mixed-reality/ct-p/MicrosoftMixedReality.

And always feel free to hit us up on Twitter @MxdRealityDev.

Convert OnMouseDown to AirTap

mdoukmdouk
edited May 2017 in Questions And Answers

Hi everybody,

I have the following script which fine works in Unity (thanks to robertbu):

` public int digit;
public GameObject correctMessage;
public GameObject falseMessage;

static int[] solution = { 1, 2, 3, 4 };
private static int[] input = { -1, -1, -1, -1 };

void OnMouseDown()
{
    input[0] = input[1];
    input[1] = input[2];
    input[2] = input[3];
    input[3] = digit;

    if (solution[0] == input[0] && solution[1] == input[1] && solution[2] == input[2] && solution[3] == input[3])
    {
        Debug.Log("Correct Order");
        correctMessage.SetActive(true);
    }
    else
    {
        falseMessage.SetActive(true);
    }
}`

...and I want to change its implementation so that instead of responding to mouse clicks, it responds to AirTaps. I came up with the following code:

`public class OrderTest : MonoBehaviour
{
public int digit;
public GameObject correctMessage;
public GameObject falseMessage;

static int[] solution = { 1, 2, 3, 4 };
private static int[] input = { -1, -1, -1, -1 };

GestureRecognizer recognizer;

void Start()
{
    recognizer = new GestureRecognizer();

    recognizer.TappedEvent += Recognizer_TappedEvent;

    recognizer.StartCapturingGestures();
}

private void Recognizer_TappedEvent(InteractionSourceKind source, int tapCount, Ray headRay)
{
    input[0] = input[1];
    input[1] = input[2];
    input[2] = input[3];
    input[3] = digit;

    if (solution[0] == input[0] && solution[1] == input[1] && solution[2] == input[2] && solution[3] == input[3])
    {
        Debug.Log("Correct Order");
        correctMessage.SetActive(true);
    }
    else
    {
        falseMessage.SetActive(true);
    }
}

}`

which however does not work with HoloLens. My project already contains the necessary InputManager prefab from HoloToolkit. AirTapping on GUIs and TapToPlace work just fine, however I cannot get this particular script to work. Any ideas?

Tagged:

Best Answers

Answers

  • I think you are missing a call to SetRecognizableGestures(GestureSettings.Tap); to tell the GestureRecognizer that you want to recognize air taps.
    Take a look at the following script:

    public class Tapable : MonoBehaviour
    {
        private GestureRecognizer recognizer;
    
        private void Start()
        {
            recognizer = new GestureRecognizer();
            recognizer.SetRecognizableGestures(GestureSettings.Tap);
            recognizer.TappedEvent += OnTapped;
            recognizer.StartCapturingGestures();
        }
    
        private void OnTapped(InteractionSourceKind source, int tapCount, Ray headRay)
        {
            // your logic
        }
    
        private void OnDestroy()
        {
            recognizer.TappedEvent -= OnTapped;
            recognizer.StopCapturingGestures();
        }
    }
    

    By the way: you do not need the HoloToolkit for using the GestureRecognizer, because it is provided by Unity (see documentation).
    If you want to write less code, use the HoloToolkit. Just implement the interface IInputClickHandler and it will handle everything for you (InputManager Prefab has to be in the scene). More info is available on GitHub.

  • That should do it!
    How exactly do I implement the IInputClickHandler interface? Do I have to be in namespace Holotoolkit.Unity?

  • mdoukmdouk
    edited May 2017

    Nope, the interface and its method are not recognized in this context. I included:
    using HoloToolkit; using HoloToolkit.Unity.InputModule; using UnityEngine.VR.WSA.Input; using UnityEngine;
    but still nothing...

  • Are you getting any compiler errors or warnings/exceptions during runtime?
    If not, what exactly are you trying to air tap? In case you have no concrete object to tap, take a look at this thread.

  • I try to airtap four objects that have a collider. I want to find if the user has airtapped them in the correct order (something like a password game). The IInputClickHandler is not recognized as a valid interface at all. Like when a libraby reference is missing. Any other ideas? Thanks a lot!

  • mdoukmdouk
    edited May 2017

    I reimported HoloToolkit and now the airtapping works! Thanks!

    My logic is false however...I have the following script and I guess I am doing something wrong, since I can never get the "Correct" message:

    `using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    using HoloToolkit;
    using UnityEngine.VR.WSA.Input;
    using HoloToolkit.Unity.InputModule;
    using System;
    public class OrderTest : MonoBehaviour, IInputClickHandler
    {
    public int digit;
    public GameObject correctMessage;
    public GameObject falseMessage;
    public GameObject waitingMessage;

    static int[] solution = { 1, 2, 3, 4 };
    private static int[] input = { -1, -1, -1, -1 };
    
    private void Start()
    {
        InputManager.Instance.PushFallbackInputHandler(gameObject);
    }
    
    public virtual void OnInputClicked(InputEventData eventData)
    {
        input[0] = input[1];
        input[1] = input[2];
        input[2] = input[3];
        input[3] = digit;
    
        if (solution[3] == input[3])
        {
            if (solution[2] == input[2])
            {
                if (solution[1] == input[1])
                {
                    if (solution[0] == input[0])
                    {
                        Debug.Log("Correct Order");
                        correctMessage.SetActive(true);
                        falseMessage.SetActive(false);
                        waitingMessage.SetActive(false);
                    }
                }
            }
        }
        else if (solution[3] != input[3] & solution[2] != input[2] & solution[1] != input[1] & solution[0] != input[0])
        {
            Debug.Log("Missing Input");
            correctMessage.SetActive(false);
            falseMessage.SetActive(true);
            waitingMessage.SetActive(false);
        }
        else
        {
            Debug.Log("False Order");
            correctMessage.SetActive(false);
            falseMessage.SetActive(false);
            waitingMessage.SetActive(true);
        }
    }
    

    }`

    If I replace OnInputClicked(InputEventData eventData) with OnMouseDown() the above script works just fine in Unity..What am I missing? Any ideas?

  • The airtapping work now! Thanks!
    The logic is however false. I have the following script:

    `
    public class OrderTest : MonoBehaviour, IInputClickHandler
    {
    public int digit;
    public GameObject correctMessage;
    public GameObject falseMessage;
    public GameObject waitingMessage;

    static int[] solution = { 1, 2, 3, 4 };
    private static int[] input = { -1, -1, -1, -1 };
    
    private void Start()
    {
        InputManager.Instance.PushFallbackInputHandler(gameObject);
    }
    
    public virtual void OnInputClicked(InputEventData eventData)
    {
        input[0] = input[1];
        input[1] = input[2];
        input[2] = input[3];
        input[3] = digit;
    
        if (solution[3] == input[3])
        {
            if (solution[2] == input[2])
            {
                if (solution[1] == input[1])
                {
                    if (solution[0] == input[0])
                    {
                        Debug.Log("Correct Order");
                        correctMessage.SetActive(true);
                        falseMessage.SetActive(false);
                        waitingMessage.SetActive(false);
                    }
                }
            }
        }
        else if (solution[3] != input[3] & solution[2] != input[2] & solution[1] != input[1] & solution[0] != input[0])
        {
            Debug.Log("Missing Input");
            correctMessage.SetActive(false);
            falseMessage.SetActive(true);
            waitingMessage.SetActive(false);
        }
        else
        {
            Debug.Log("False Order");
            correctMessage.SetActive(false);
            falseMessage.SetActive(false);
            waitingMessage.SetActive(true);
        }
    }
    

    }
    `

    If I replace the OnInputClicked(InputEventData eventData) with OnMouseDown(), this script works perfect in Unity. What am I missing? Any ideas?

  • ReeleyReeley ✭✭✭
    edited May 2017

    This shouldnt work at all. In your else if you have to use && instead of &. Also you can do the same && thingy in your if so its a little bit nicer structured.

    I think missing input should be designed like this:
    else if(input[3] == -1 || input[2] == -1 || input[1] == -1 || input[0] == -1)

    Furthermore where does your digit variable get set? with an other script?

  • mdoukmdouk
    edited May 2017
    • it only works with one "&", since I am trying to identify if at least one of the conditions is false. "&&" means that all conditions must be either true or false in order for the outer if to be true
    • In my if I did it that way just to test if the conditions are evaluated sequentially (beginner in programming). I have another version were if is also implemented with "&&". I guess it works identically but one is "cleaner" than the other
    • Missing Input is now implemented your way
    • The digit variable is defined in the Unity Editor. I have 4 cubes and the script is attached to each one of them. By changing the digits in editor, I can change the correct clicking "combination"

    I tried the revised version but still no luck. when I click the first correct cube I get the false message and it stay so even if I click the cubes in the correct order...

  • ReeleyReeley ✭✭✭

    Here you go:

    using UnityEngine;
    using HoloToolkit.Unity.InputModule;
    
    public class ForumTest : MonoBehaviour, IInputClickHandler {
    
        public int digit;
    
        static int[] solution = { 1, 2, 3, 4 };
        static int[] input = { -1, -1, -1, -1 };
    
        private void Start()
        {
            //InputManager.Instance.PushFallbackInputHandler(gameObject);
        }
    
        public virtual void OnInputClicked(InputClickedEventData eventData)
        {
            input[0] = input[1];
            input[1] = input[2];
            input[2] = input[3];
            input[3] = digit;
    
            if (solution[3] == input[3] && solution[2] == input[2] && solution[1] == input[1] && solution[0] == input[0])
            {
                Debug.Log("Correct Order");
            }
            else if (input[3] == -1 || input[2] == -1 || input[1] == -1 || input[0] == -1)
            {
                Debug.Log("Missing Input");
            }
            else
            {
                Debug.Log("False Order");
            }
        }
    }
    
    1. You dont need the PushFallback because you have your script on the gameobject itself so it will automatically get called.
    2. The OnInputClicked takes in an InputClickedEventData) at least for me but i think they changed something there so maybe its different now (Im using a about a month old Holotoolkit version)
    3. You have to readd your Messages gameojects i deleted them for testing
    4. Make sure you have a collider on all of your boxes
  • Still not working....
    Maybe its better to explain the problem from the beginning: I am trying to create a puzzler, where the player must click the 4 objects, each representing a number, in the correct order (like a safe-combination) to win. After 4 airtaps, I want to check if the correct sequence was selected. I have implemented that in Unity with OnMouseDown() and it works but the transition to HoloLens was harder than usual.

    Could anybody think of another approach to solve this one?

  • ReeleyReeley ✭✭✭

    Well i rebuild exactly what you want and for me its working, but when it is also working for you with the OnMouseDown, does the function with the Holotoolkit API get called at all?

  • mdoukmdouk
    edited May 2017

    Thanks for your time!
    I do not completely understand what you mean with "...but when it is also working for you with the OnMouseDown, does the function with the Holotoolkit API get called at all?..."

    Btw I have created an entirely new project in Unity, imported the newest HoloToolkit, created your script, attached it to 4 objects with trigger colliders, included all other necessary HoloToolkit components (HoloLensCamera, Lights, Cursor, InputManager) and still it does not work. On my first click I see the Missing Input message and on my second the False message. Then the False message stays on whatever I do / whichever object I click.

    I realize that the logic is false with OnInputClicked(args), which apparently works in a very different way in comparison to OnMouseDown().

  • ReeleyReeley ✭✭✭

    What i meant by that is, if the method gets called at all, when you click, but i guess this seems to work. That the false method appears and stays should be normal after your fourth click cause the value never gets to -1 again. If you click the correct order though it should print the correct order message.

    I have no idea why this is not working for you and cant help you anymore. Maybe you can upload your project somewhere so i can take a look.

  • You can download a striped-out project here: https://www.dropbox.com/s/uspuzxep5mp3tl9/test.zip?dl=0

    Thanks a bunch for your time and effort!

  • ReeleyReeley ✭✭✭

    Your project works absolutely fine for me. The only thing i noticed is that you use a old Unity version maybe you can try upgrading it. Im currently using 5.6.0f3 and switched your project to that.

    PS: Ansonsten bin ich mit meinem Latein am Ende :D

  • Scratch the last post. This striped-out version works! the entire project still does not work though...I have to figure that out...
    Now I could use some help with the logic. I want the result "Correct" or "False" to be shown only after the user has clicked 4 times. Before that, the waiting message should appear. Should I use a for loop with a counter?

  • ReeleyReeley ✭✭✭
    edited May 2017

    This should also work^^

    First Input:
    { 1, -1, -1, -1 };
    Second Input:
    { 2, 1, -1, -1 };
    Third Input:
    { 3, 2, 1, -1 };
    Fourth Input:
    { 4, 3, 2, 1 }; -> right order

Sign In or Register to comment.