Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 13 Next capture
2021 2022 2023
1 capture
13 Jun 22 - 13 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
0
Question by Cooleobrad · Jun 24, 2020 at 04:11 PM · vroculus

How to get VR button press input on only the first frame it is pressed - XR Toolkit

I've recently learned that detecting a button press on a VR controller using:

 public class ReadInput : MonoBehaviour
 {
     //Assigned to the RightHand Controller
     public XRController controller = null;
     InputDevice device;
     void Start (){
         device = Input.GetDeviceAtXRNode(controller.controllerNode);
     }
     void Update()
     {
         if(device.TryGetFeatureValue(CommonUsages.primaryButton, out bool buttonValue) && buttonValue)
         {
             Debug.Log(" pressing a");
         }
 }

Returns true every frame that the button is pressed. I expected this code to work like normal keyboard input i.e. Input.GetKeyDown(KeyCode.Space), but while using that line of code would work fine in my project, getting input from a VR button press does not.

How can I fix this code to work more like Input.GetKeyDown(KeyCode.Space)where it only returns true on the first frame the button was pressed? Is there a different function I could use that would achieve what I'm looking for, or how can I ensure it doesn't keep returning true every single frame?

Comment
Add comment
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

2 Replies

· Add your reply
  • Sort: 
avatar image
10

Answer by wpetillo · Jun 26, 2020 at 05:22 AM

Attach this to an object in your scene, connect the exposed UnityEvents to public methods in your game logic that respond to button presses, and never worry about XR input again. Supports touch and full press as well as first frame, last frame, and continuous. For an understanding of how to get the first frame of a binary state change, see the Update method in XRBinding. For example usage, see https://github.com/Will9371/Character-Template, an open-source project which also includes touchpad input, keyboard input, 1st and 3rd person character control, and 3rd person VR character control, and lots of other things.

 using System;
 using UnityEngine;
 using UnityEngine.Events;
 using UnityEngine.XR;
 using UnityEngine.XR.Interaction.Toolkit;
 
 public class XRInput : MonoBehaviour
 {
     #pragma warning disable 0649
     [SerializeField] XRController controller;
     [SerializeField] XRBinding[] bindings;
     #pragma warning restore 0649
     
     private void Update()
     {
         foreach (var binding in bindings)
             binding.Update(controller.inputDevice);
     }
 }
 
 [Serializable]
 public class XRBinding
 {
     #pragma warning disable 0649
     [SerializeField] XRButton button;
     [SerializeField] PressType pressType;
     [SerializeField] UnityEvent OnActive;
     #pragma warning restore 0649
     
     bool isPressed;
     bool wasPressed;
 
     public void Update(InputDevice device)
     {
         device.TryGetFeatureValue(XRStatics.GetFeature(button), out isPressed);
         bool active = false;
         
         switch (pressType)
         {
             case PressType.Continuous: active = isPressed; break;
             case PressType.Begin: active = isPressed && !wasPressed; break;
             case PressType.End: active = !isPressed && wasPressed; break;
         }
         
         if (active) OnActive.Invoke();
         wasPressed = isPressed;
     }
 }
 
 public enum XRButton
 {
     Trigger,
     Grip,
     Primary,
     PrimaryTouch,
     Secondary,
     SecondaryTouch,
     Primary2DAxisClick,
     Primary2DAxisTouch
 }
 
 public enum PressType
 {
     Begin,
     End,
     Continuous
 }
 
 public static class XRStatics
 {
     public static InputFeatureUsage<bool> GetFeature(XRButton button)
     {
         switch (button)
         {
             case XRButton.Trigger: return CommonUsages.triggerButton;
             case XRButton.Grip: return CommonUsages.gripButton;
             case XRButton.Primary: return CommonUsages.primaryButton;
             case XRButton.PrimaryTouch: return CommonUsages.primaryTouch;
             case XRButton.Secondary: return CommonUsages.secondaryButton;
             case XRButton.SecondaryTouch: return CommonUsages.secondaryTouch;
             case XRButton.Primary2DAxisClick: return CommonUsages.primary2DAxisClick;
             case XRButton.Primary2DAxisTouch: return CommonUsages.primary2DAxisTouch;
             default: Debug.LogError("button " + button + " not found"); return CommonUsages.triggerButton;      
         }
     }
 }
Comment
Add comment · Show 8 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image Eno-Khaon · Jun 26, 2020 at 06:28 AM 0
Share

Wow, talk about not having seen the forest for the trees. This is a very solid solution! Once the setup's done (i.e. all intended/desired buttons), this looks like it handles everything very cleanly.

avatar image InsaneDuane · Sep 24, 2020 at 07:04 PM 0
Share

Thank you for this!!! I am attempting to get away from the Oculus OVR package and use the slimmed down/ less bloated XR Interaction Toolkit. Trying to figure out the input methods are confounding me at the moment and this solution for button presses is working great! Now I am going to tackle actually moving in VR using your script...

avatar image InesHilz · Feb 24, 2021 at 03:10 PM 0
Share

Thank you, good sir. God bless ya

avatar image tbgames3000 · Sep 03, 2021 at 10:41 AM 0
Share

I made an empty game object and added this code to it but I'm unable to add XR controllers into the XRController field. I thought I'd just drag a left or right hand controller right onto it and it would work but it's not working. The left/right hand controllers in my scene are Action Based. Please let me know what I'm doing wrong. Thank you.

avatar image wpetillo · Sep 03, 2021 at 08:49 PM 0
Share

@tbgames3000 Hard to say without seeing the full context, but I am guessing it is because of the action-based system--one of the main reasons I made this was to avoid dealing with all the over-engineered nonsense out there. In any case, the best way to troubleshoot (this, or pretty much anything else) would be to create a new project, import the .UnityPackage file (from here: https://github.com/Will9371/Character-Template) for quick setup, and check out one of the example scenes to see how it all works in context. Once you understand how it works, observe what is different about your project and consider if it meets your needs.

avatar image tbgames3000 wpetillo · Sep 03, 2021 at 09:13 PM 0
Share

@wpetillo I'll try what you told me to do and see if I can make it work in my project. Thanks a lot!

Show more comments
avatar image
0

Answer by Eno-Khaon · Jun 24, 2020 at 11:34 PM

One way to handle it would simply be to track it yourself. If the button wasn't pressed as of the previous frame, but it is on the current one, there's your GetKeyDown() equivalent.

 Dictionary<CommonUsages, bool> rightHandState;
 // ...

 void Start()
 {
     rightHandState = new Dictionary<CommonUsages, bool>();
     rightHandState[CommonUsages.primaryButton] = false; // Assumed not held when starting game, while also initializing the value
 }

 // ...

 void Update()
 {
     if(device.TryGetFeatureValue(CommonUsages.primaryButton, out bool buttonValue))
     {
         if(buttonValue != rightHandState[CommonUsages.primaryButton])
         {
             // Button was pressed or released this frame
             // Do something with it here...

             // ... then make sure to set the last known state of it for reference next Update()
             rightHandState[CommonUsages.primaryButton] = buttonValue;
         }
     }
 }


This setup should be easy enough to adapt to support more button types, where the Dictionary will automatically be able to support as many of them as are needed.

That said, if you have a very small/finite number of buttons you intend to allow, it would be cheaper/viable to simply define a Boolean to keep track of the last known state of each given button, rather than using the Dictionary.

Comment
Add comment · Show 7 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image Cooleobrad · Jun 25, 2020 at 12:20 AM 0
Share

Thank you, but this code gives me some errors. 'CommonUsages': static types cannot be used as type arguments and Argument1: cannot convert from 'UnityEngine.XR.InputFeatureUsage<bool>' to 'UnityEngine.XR.CommonUsages'

avatar image Eno-Khaon Cooleobrad · Jun 25, 2020 at 01:04 AM 0
Share

Whoops, I should've done my research better. I thought, given the presentation and usage, that CommonUsages was an enumerator.

Well, then, in that case, I guess you'd just want to use an independent Boolean to keep track of any given value ins$$anonymous$$d, then.

 bool rightHandLastState = false;
 // ...
 rightHandLastState = buttonValue;
avatar image Cooleobrad Eno-Khaon · Jun 25, 2020 at 02:07 AM 0
Share

$$anonymous$$y code currently looks like this:

 bool rightHandLastState = false;
      // ...
      void Start()
      {
          rightHandLastState = false; // Assumed not held when starting game, while also initializing the value
      }
      // ...
      void Update()
      {
          if(device.TryGetFeatureValue(CommonUsages.primaryButton, out bool buttonValue))
          {
              if(buttonValue != rightHandLastState)
              {
                  // Button was pressed or released this frame
                  // Do something with it here...
                  // ... then make sure to set the last known state of it for reference next Update()
                  rightHandLastState = buttonValue;
              }
          }
      }

But this doesn't seem to ever enter the second if statement

Show more comments

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

175 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

How to make the swipe on Oculus Go 3 Answers

How to make an undo redo system in runtime for GameObjects? 2 Answers

Andriod (Oculus Quest 2 app) locked at 30 fps 1 Answer

How to detect button down/up in xr interaction toolkit in unity xr oculus? 0 Answers

open xr floor height not working 0 Answers


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges