0

I've been googling this for 10 hours and I'm running out of ideas. I found several video-tutorials and written-tutorials but none of them really works or they're overkill.

I have VR Unity (2020.3.16f) project designed to be run on Quest 2. I'm not using OpenXR. I already created hand, created one simple grabbing animation, added animation to Animator, created transitions, and set "IsGrabbed" parameter. Now I'm looking a simple way to change "IsGrabbed" to true/false whenever I grab/release anything. I'm expecting something like this:

public class grabber : MonoBehaviour
{
    // Start is called before the first frame update
    Animator animator;
    ???

    void Start()
    {
       ???
    }

    // Update is called once per frame
    void Update()
    {
        if (???)
           {
               animator.SetBool("IsGrabbing", true);
           }

        elseif (???)
           {
               animator.SetBool("IsGrabbing", false);
           }
    }
}

Please help. We're talking about VR here so I'm sure grabbing animation is the very basics of very basics of very basics. It can't be any difficult.

Best regards

NastyKhan
  • 11
  • 2

2 Answers2

0

First of all, I highly recommend watching this video by Justin P Barnett to get a much better overview of how this all works.

If you don't want to go that route for some reason, there are other options available to you. One such option is the "Player Input" component, which can act as a bridge between your input devices and your code. Most XR packages these days use the new Input System package, and it makes life easier, so I will assume you have that installed.

First, you will need to create an Input Actions asset, which can be done in the project pane: right-click -> Create -> Input Actions. There are many tutorials which explain this asset in detail, but here is a simple setup to get you started. Double click on the new asset to open the editing window, and create a new Action Map. In the "Actions" list, create a new action with action type Value, Control Type Axis, and in the dropdown arrow on your new action set the path to the input source. As an example source path, I will use XR Controller -> XR Controller -> XR Controller (Left Hand) -> Optional Controls -> grip. Make sure to click Save Asset before closing the window.

Create a script similar to this:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.InputSystem;

public class ControllerInputReceiver : MonoBehaviour {
    public void FloatToScale(InputAction.CallbackContext context) {
        float val = 0.1f + 0.1f * context.ReadValue<float>();
        transform.localScale = new Vector3(val, val, val);
    }
}

Create a cube somewhere visible in your scene, and add the Input Action Manager component to it, and drag your created Input Actions asset to its list of Action Assets. Then add the ControllerInputReceiver script. Also on this cube, create a Player Input component and drag your Input Actions asset to its Actions element. Choose your map as the default map and change behavior to Invoke Unity Events. Under the events drop down, you should see an element for the Action you created earlier. Drop your Controller Input Receiver component into this Action and select the FloatToScale function.

In theory it should work at this point. Build the game to your device and see if pulling the grip causes the cube to resize. If it does, then you can replace your Update function with:

void SetGrabbing(InputAction.CallbackContext context) {
    animator.SetBool("IsGrabbing", context.ReadValue<float>() > cutoff);
}

If you are still having issues at this point, I really recommend checking out these youtube channels. I only started VR a couple of months ago and learned everything I know so far from these people. JustinPBarnett, VRwithAndrew, ValemVR, LevelUp2020. (Links removed because it kept screwing up my post)

Note, the new input system has button options instead of value/axis options for VR devices. These may be closer to what you want, but I had no luck getting them to work today.

Also note, depending on how you organize your code, you may or may not need the "Input Action Manager" component somewhere in your scene with your input actions asset in its list. It enables your actions for you, without you needing to do this programmatically.

R B
  • 61
  • 4
  • Thank you good sir. Yes, I watched several tutorials of mentioned people before I posted my question. They seem over-complicated compared to simplicity of setting up everything else (movements, hand tracking, grabbing, throwing etc.) Especially that having animated hands sounds like basic piece of functionality. I also found some of those video-tutorials out-dated, especially early Valem's tutorials (from 2019). As for your solution I ended up at "ControllerInputReceiver script" part as I couldn't find one plus I have reached point when I don't know anymore what I'm doing anyway... – NastyKhan Aug 16 '21 at 19:08
  • Yes, unfortunately the prewritten scripts from Unity only handle tracking / grabbing / throwing so far, and not animation. I agree that many of the video tutorials are becoming outdated since VR is rapidly changing, but luckily the video I linked is still sufficiently up to date with the latest Unity and VR packages. I recently spent an hour or two copying everything he did in a temp project to learn it for myself, and I don't recall anything breaking for the latest packages. If my ControllerInputReceiver script I wrote is not working for you, then that video is the best advice I have. – R B Aug 16 '21 at 23:22
  • Thank you again. I'll check that soon. – NastyKhan Aug 18 '21 at 11:10
0

Another solution would be:

Using the OVR plugin and Hands prefab (for left and right), to check whether the rotation of each of the fingers on a specific axis (ex. Z-Axis) falls under a specific range-meaning fingers are grasping/flexed.

By referencing for example the Transform of b_l_index1 , which is the corresponding part of the Index Finger within the model, you can check its local roation every frame and trigger the event of grasping when all fingers are rotated to a specific angle. Subsequently, triggering the animation you need.