Search Unity

Supporting Single or Multiple Motion Controller inputs

Discussion in 'VR' started by Relaycars, Feb 6, 2018.

  1. Relaycars

    Relaycars

    Joined:
    Mar 28, 2016
    Posts:
    12
    Hi Everyone I am developing an Immersive app and having a little trouble figuring out how to support both single an dual Motion Controller inputs( if that is even possible) . I will include my code below but currently I am polling the Interaction source state of both controllers and and applying my interaction logic after they meet the input thresholds.

    What I'm trying to do is get the number of current Interaction source states using
    Code (CSharp):
    1. var interactionSourceState = InteractionManager.GetCurrentReading ();
    and based on the length of the returned array . Determine if one or two controllers are being detected and then handle the input based on the respective indexes for one of both controllers. Is my thinking incorrect? Am I missing something about how the Interaction Source States are working ?

    Here is my code for reference of how I am implementing this :
    Code (CSharp):
    1.  var interactionSourceState = InteractionManager.GetCurrentReading ();
    2.              //*** If Single controller
    3.              if (interactionSourceState.Length == 1) {
    4.              //*** Controller Stick 1
    5.                  if (interactionSourceState [0].thumbstickPosition.x >= 0.1f) {
    6.                      Debug.Log (" Left Stick moved Left");
    7.                    
    8.                  }
    9.                  if (interactionSourceState [0].thumbstickPosition.x <= -0.1f) {
    10.                      Debug.Log (" Left Stick moved Right");
    11.                    
    12.                  }
    13.                  //*** Touchpad 1
    14.                  if (interactionSourceState [0].touchpadPosition.x >= 0.1f) {
    15.                      Debug.Log (" Left Stick moved Left");
    16.                
    17.                  }
    18.                  if (interactionSourceState [0].touchpadPosition.x <= -0.1f) {
    19.                      Debug.Log (" Left Stick moved Right");
    20.                      Vector3 rotation = Vector3.up * 3.0f * Time.deltaTime * sensitivity;
    21.                      this.transform.Rotate (rotation);
    22.                  }
    23.                  //*** If two controllers
    24.              } else if (interactionSourceState.Length > 1) {
    25.                  //*** Controller Stick 1
    26.                  if (interactionSourceState [0].thumbstickPosition.x >= 0.1f) {
    27.                      Debug.Log (" Left Stick moved Left");
    28.                
    29.                  }
    30.                  if (interactionSourceState [0].thumbstickPosition.x <= -0.1f) {
    31.                      Debug.Log (" Left Stick moved Right");
    32.                
    33.                  }
    34.                  //*** Touchpad 1
    35.                  if (interactionSourceState [0].touchpadPosition.x >= 0.1f) {
    36.                      Debug.Log (" Left Stick moved Left");
    37.                
    38.                  }
    39.                  if (interactionSourceState [0].touchpadPosition.x <= -0.1f) {
    40.                      Debug.Log (" Left Stick moved Right");
    41.                
    42.                  }
    43.                  //*** Control Stick 2
    44.                  if (interactionSourceState [1].thumbstickPosition.x >= 0.1f) {
    45.                      Debug.Log (" Right Stick moved Left");
    46.            
    47.                  }
    48.                  if (interactionSourceState [1].thumbstickPosition.x <= -0.1f) {
    49.                      Debug.Log (" Right Stick moved Right");
    50.            
    51.                  }
    52.                  //*** Touchpad 2
    53.                  if (interactionSourceState [1].touchpadPosition.x >= 0.1f) {
    54.                      Debug.Log (" Left Stick moved Left");
    55.                
    56.                  }
    57.                  if (interactionSourceState [1].touchpadPosition.x <= -0.1f) {
    58.                      Debug.Log (" Left Stick moved Right");
    59.                
    60.                  }
    61.              }

    Thank you very much , any and all input is appreciated I feel like I might be missing something in my implementation .
     
  2. Unity_Wesley

    Unity_Wesley

    Unity Technologies

    Joined:
    Sep 17, 2015
    Posts:
    558
    Interaction manager will already pick up any input from the spatial input controllers that are connected and sending input to the app. You can tell the interaction manager I only want the left or the right controller or both when the event is updated. The interaction manager update event will grab all the information and input you need from any of the controllers reporting, so I don't think you need the GetCurrentReading().

    My suggestion is to pull the data from the left and right controller in the update function for interaction manager, then you can sort the controllers out based on left, right, hand, or unknown. Or if you using an Xbox controller you can check to see if it is that type of controller via input manager or in script.
     
  3. Relaycars

    Relaycars

    Joined:
    Mar 28, 2016
    Posts:
    12

    Thank you for this @Unity_Wesley , When I tried looking up the functions or variables/ parameters for left and right controllers from the input manager I was unable to find them, would you happen to have nay example code or a scripting reference I can take a look at for an example ?
     
  4. JasonCostanza

    JasonCostanza

    Unity Technologies

    Joined:
    May 23, 2017
    Posts:
    404
    You can get InteractionManager events by using some of the below examples. Our documentation on those API's are still in progress and are not posted yet. But here's some code chunks I extracted from one of our test scenes, hopefully I didn't miss any important bits.

    these events do not care which hand is submitting them or if a hand is missing/off
    Code (csharp):
    1.  
    2.    void Start()
    3.    {
    4.        // Setting up events for the interaction manager
    5.        InteractionManager.InteractionSourceDetected += SourceManager_SourceDetected;
    6.        InteractionManager.InteractionSourceLost += SourceManager_SourceLost;
    7.        InteractionManager.InteractionSourcePressed += SourceManager_SourcePressed;
    8.        InteractionManager.InteractionSourceReleased += SourceManager_SourceReleased;
    9.        InteractionManager.InteractionSourceUpdated += SourceManager_SourceUpdated;
    10.      
    11.        InteractionManager.GetCurrentReading();
    12.    }
    13.  
    14.    void Update()
    15.    {
    16.        InteractionManager.GetCurrentReading();
    17.    }
    18.  
    These can be modified to only react to a certain hand, if you wish, with something like this
    Code (csharp):
    1.  
    2.  private void SourceManager_SourceUpdated(InteractionSourceUpdatedEventArgs obj)
    3.    {
    4.        InteractionSourcePose statePose = obj.state.sourcePose;
    5.  
    6.        if (obj.state.source.handedness == InteractionSourceHandedness.Right)
    7.        {
    8.        }
    9.  
    10.        if (obj.state.source.handedness == InteractionSourceHandedness.Left)
    11.        {
    12.        }
    13.  
    14.        if (obj.state.source.handedness == InteractionSourceHandedness.Unknown)
    15.        {
    16.        }
    17.  
    18.    void OnDestroy()
    19.    {
    20.        InteractionManager.InteractionSourceDetected -= SourceManager_SourceDetected;
    21.        InteractionManager.InteractionSourceLost -= SourceManager_SourceLost;
    22.        InteractionManager.InteractionSourcePressed -= SourceManager_SourcePressed;
    23.        InteractionManager.InteractionSourceReleased -= SourceManager_SourceReleased;
    24.        InteractionManager.InteractionSourceUpdated -= SourceManager_SourceUpdated;
    25.    }
    26.  
     
  5. tfrantz

    tfrantz

    Joined:
    Dec 7, 2017
    Posts:
    7
    Working with the hololens, I've been trying to get the world hand position with the above code. In the Unity editor, It's not updating, or registering any hand positions for me, unfortunate. Does this only register hand positions when deployed from the hololens?

    Unity 2017.2.0f3

    Code (CSharp):
    1.  public Vector3 HandPosition;
    2.  
    3.     void Start()
    4.     {
    5.         InteractionManager.InteractionSourceUpdated += SourceManager_SourceUpdated;
    6.         InteractionManager.GetCurrentReading();
    7.     }
    8.  
    9.     private void Update()
    10.     {
    11.         InteractionManager.GetCurrentReading();
    12.     }
    13.  
    14.     private void SourceManager_SourceUpdated(InteractionSourceUpdatedEventArgs obj)
    15.     {
    16.         obj.state.sourcePose.TryGetPosition(out HandPosition);
    17.     }
    18.  
    19.     void OnDestroy()
    20.     {
    21.         InteractionManager.InteractionSourceUpdated -= SourceManager_SourceUpdated;
    22.     }
     
  6. JasonCostanza

    JasonCostanza

    Unity Technologies

    Joined:
    May 23, 2017
    Posts:
    404
  7. tfrantz

    tfrantz

    Joined:
    Dec 7, 2017
    Posts:
    7
    Sorry is this is a total noob question, but if TryGetPosition returns true, does it not output to the vector3 associated with out? "TryGetPosition(out Vector3)"

    I have all the above in the same script as the rest of the code I need the current world hand position of, or is this this wrong place?

    Perhaps there is an example usage?

    Thank you!
     
  8. JasonCostanza

    JasonCostanza

    Unity Technologies

    Joined:
    May 23, 2017
    Posts:
    404
    It does, the TryGet returns true/false to say "Yes, I've got your data here." and it defaults to returning grip position unless you specify otherwise. But so far you've only retrieved what that vector3 is, you haven't used it by setting some game object's position to it for example, which you would do in the SourceUpdated function. That make sense?

    Code (CSharp):
    1. void Start()
    2.     {
    3.         TrackHand = GameObject.CreatePrimitive(PrimitiveType.Sphere);
    4.     }
    5.  
    6. private void Update()
    7.     {
    8.         InteractionManager.GetCurrentReading();
    9.     }
    10.  
    11. private void SourceManager_SourceUpdated(InteractionSourceUpdatedEventArgs obj)
    12.     {
    13.         InteractionSourcePose statePose = obj.state.sourcePose; // sets up shorthand for next line
    14.  
    15.         statePose.TryGetPosition(out GripPos);
    16.  
    17.         TrackHand.transform.position = GripPos;
    18.     }
    if you want something like a pointer position instead of grip, use this in the TryGet

    Code (CSharp):
    1. statePose.TryGetPosition(out PointerPos, InteractionSourceNode.Pointer);
     
    Last edited: Mar 26, 2018
  9. tfrantz

    tfrantz

    Joined:
    Dec 7, 2017
    Posts:
    7
    Thanks for the reply. Turned out that the hand tracking only worked for me when my program deployed to the Hololens; perfectly I would like to say. From the unity editor, no hand position data was returned. Is this normal?
     
  10. JasonCostanza

    JasonCostanza

    Unity Technologies

    Joined:
    May 23, 2017
    Posts:
    404
    Are you using simulation in editor via the Holographic Emulation tab? Or, are you remoting to the device from the editor?