Search Unity

Vive object interaction

Discussion in 'AR/VR (XR) Discussion' started by TheHeavySoldier, Oct 20, 2016.

  1. TheHeavySoldier

    TheHeavySoldier

    Joined:
    Oct 20, 2016
    Posts:
    7
    Hello everyone,

    I got my Vive 5 days ago and have been enjoying it thoroughly and decided I'd give development a shot with Unity.

    I'm currently trying to write my own interaction script, I know there are free scripts out there but I'd like to learn something in the process and I like to know what my script does.
    Anyway, I'm currently kind of stuck and need a hint.

    I can register trigger presses, I can register when my controller is colliding with a rigid body and I can, sort of, interact with it.

    What I mean with that is, I'm using MoveTowards to move the interactable item to the controller. The interact ble item, however, will slowly move downwards as if gravity is slowly pulling it down.
    That's problem 1.

    Problem 2 is, when I release the trigger, sometimes it'll let the interactable item go, and other times it'll keep holding it.

    Personally I feel the problem is with my void OnTriggerExit(Collider collider) method.
    ViveWirelessController.cs:
    Code (csharp):
    1.  
    2. using UnityEngine;
    3.  
    4. using System.Collections;
    5.  
    6. publicclassViveWirelessController : MonoBehaviour {
    7.  
    8. // Shorten name
    9.  
    10. privateulong triggerButton = SteamVR_Controller.ButtonMask.Trigger;
    11.  
    12. // Create an InteractItem object?
    13.  
    14. private InteractItem interactItem;
    15.  
    16. // Retrieve the index of the controller. (Can be different for every game launch).
    17.  
    18. private SteamVR_Controller.Device controller {
    19.  
    20. get {
    21.  
    22. return SteamVR_Controller.Input((int)GetComponent<SteamVR_TrackedObject>().index);
    23.  
    24. }
    25.  
    26. }
    27.  
    28. // Use this for initialization
    29.  
    30. void Start () {
    31.  
    32.  
    33.  
    34. }
    35.  
    36.  
    37.  
    38. // Update is called once per frame
    39.  
    40. void Update () { // FixedUpdate?
    41.  
    42. // Check to see if the player is pressing the triggerButton and if there is currently an interactItem.
    43.  
    44. if (controller.GetPressDown(triggerButton) && interactItem !=null) {
    45.  
    46. // Debug.Log("Trigger Button Pressed");
    47.  
    48. // Start the interaction for the current controller.
    49.  
    50. interactItem.BeginInteraction(this);
    51.  
    52. }
    53.  
    54. // Check to see if the player let go of the triggerButton and if there is currently an interactItem.
    55.  
    56. if (controller.GetPressUp(triggerButton) && interactItem !=null) {
    57.  
    58. // Debug.Log("Trigger Button Released");
    59.  
    60. // End the interaction for this controller.
    61.  
    62. interactItem.EndInteraction(this);
    63.  
    64. }
    65.  
    66. }
    67.  
    68. void OnTriggerEnter(Collider collider) {
    69.  
    70. // Debug.Log("OnTriggerEnter");
    71.  
    72. // Set the interactItem to the item the controller is currently colliding with.
    73.  
    74. interactItem = collider.GetComponent<InteractItem>();
    75.  
    76. }
    77.  
    78.  
    79.  
    80. void OnTriggerExit(Collider collider) {
    81.  
    82. // Debug.Log("OnTriggerExit");
    83.  
    84. // Check to see if the trigger is being pressed.
    85.  
    86. if (controller.GetPressUp(triggerButton)) {
    87.  
    88. // If the trigger is not being pressed, allow interactItem to be set to null;
    89.  
    90. interactItem =null;
    91.  
    92. // Debug.Log("interactItem is null");
    93.  
    94. }
    95.  
    96. }
    97.  
    98. }
    99.  
    100.  

    InteractItem.cs
    Code (csharp):
    1.  
    2. using UnityEngine;
    3.  
    4. using System.Collections;
    5.  
    6. publicclassInteractItem : MonoBehaviour {
    7.  
    8. private ViveWirelessController currentController;
    9.  
    10. privatefloat velocity =1000f;
    11.  
    12. privatebool currentlyInteracting;
    13.  
    14. // Use this for initialization
    15.  
    16. void Start () { // Can be changed to Awake for now I think?
    17.  
    18. currentlyInteracting =false;
    19.  
    20. }
    21.  
    22.  
    23.  
    24. // Update is called once per frame
    25.  
    26. void FixedUpdate () {
    27.  
    28. if (currentlyInteracting) {
    29.  
    30. // Took this from the MoveTowards documention on the Unity website.
    31.  
    32. float step = velocity * Time.fixedDeltaTime;
    33.  
    34. // Move the InteractItem towards the currentController's position.
    35.  
    36. this.transform.position = Vector3.MoveTowards(this.transform.position, currentController.transform.position, step);
    37.  
    38. // Set currentController as the new parent of the this InteractItem.
    39.  
    40. this.transform.SetParent(currentController.transform, true); // I'm not sure if I'm properly applying SetParent.
    41.  
    42. }
    43.  
    44. }
    45.  
    46. publicvoid BeginInteraction(ViveWirelessController controller) {
    47.  
    48. // Debug.Log("BeginInteraction");
    49.  
    50. // set the currentController to the controller calling BeginInteraction
    51.  
    52. currentController = controller;
    53.  
    54. // Set currentlyInteracting to true to check if controller is referencing to an existing object.
    55.  
    56. currentlyInteracting =true;
    57.  
    58. }
    59.  
    60. publicvoid EndInteraction(ViveWirelessController controller) {
    61.  
    62. // Debug.Log("EndInteraction");
    63.  
    64. // Set currentController to null. There is no interaction anymore, remove the reference to the controller.
    65.  
    66. currentController =null;
    67.  
    68. // Set currentlyInteracting to false to check if controller is referencing to an existing object.
    69.  
    70. currentlyInteracting =false;
    71.  
    72. }
    73.  
    74. }
    75.  
    76.  

    Code looks a little messy, not sure why the website decided to format it like that but oh well.

    If someone could point me in the right direction or give me a hint. (Maybe more efficient method that I could use instead) that'd be great.

    Thanks in advance.
     
  2. NickAtUnity

    NickAtUnity

    Unity Technologies

    Joined:
    Sep 13, 2016
    Posts:
    84
    For the first issue, if you have a rigid body on your object, try setting isKinematic to true when you're picking it up first (and also use the MovePosition method on the Rigidbody to move it). Kinematic bodies only respond to scripted movement so nothing in the physics system will move it.

    If you don't want to make it kinematic, you can also just set useGravity to false and that will stop gravity from applying.

    Your second issue seems to be a problem in your logic. You are tracking exit events to null out your reference and seem to be handling only the frame when the button is released (assuming that's what the GetPressUp method you're calling is for). What you might try instead is this:
    1. OnTriggerEnter sets a new variable like "potentialItem" which is the thing you can interact with. OnTriggerExit checks to see if the object is the potentialItem and, if so, sets potentialItem to null.
    2. In your Update, if you press a button take the potentialItem, call BeginInteraction, and assign that to your interactItem. When you release the button, call your EndInteraction set interactItem to null.
    By separating out the item you could interact with from the one you are interacting with you should have more reliable results. This also keeps input logic in Update where you generally want it, rather than scattering it through event handlers.

    Hope that helps!
     
  3. TheHeavySoldier

    TheHeavySoldier

    Joined:
    Oct 20, 2016
    Posts:
    7
    Thank you Nick, I'll try to see if I can apply your recommendations to my script.

    Thanks again.
     
  4. TheHeavySoldier

    TheHeavySoldier

    Joined:
    Oct 20, 2016
    Posts:
    7
    Okay, so it's been a while. Busy with school and what not.

    Anyway I applied your suggestions and it seems to be working. (I do want it to keep interacting with other rigidbodies so I'm setting the gravity to false. Your addition to the OnTriggerEnter and OnTriggerExit fixed the issue with it sometimes not releasing the item, and I also added another variable which is the same as the possibleInteractItem and InteractItem but for the rigidbody which I pass as an argument to the BeginInteraction method to set the gravity in the BeginInteraction method. Not sure if it's the smartest way to do it but that way I move the item and set the gravity in the same method. Seemed the most logical to me. (I guess I could also turn off the gravity in the if (controller.GetPressDown(triggerButton) statement).

    Now I'm having a new problem though. When I throw the object into the air it'll just fall to the floor. It's not realistic.

    I feel I'm probably going to have to write a custom function that'll move the item towards the Vive controller by applying some sort of force.

    a few years I used to play Gmod and write expression 2 chips and I recall there being a function called. .applyForce() and you'd have to use the deltaposition of the item and the player (if you wanted the item to follow the player), velocity and the os.time or whatever it was called.
    But I'm not quite sure how I'd go about doing this in Unity. I'm thinking about Rigidbody.AddForce() but I'm not sure.


    EDIT---------------------

    Actually scratch that.

    I've been looking around some more and found Rigidbody.velocity = new Vector3 (0,0,0).

    I'm currently using this (rigidBody.velocity = deltaPos * velocity * Time.FixedDeltaTime) which is actually working pretty decently.

    deltaPos = controllerposition - itemposition
    velocity = 1000f

    However there is no rotation so I'll have to look into that. probably apply some sort of rotationVelocity or force.

    I also want to incorporate the mass of the object so I'll experiment some more.

    EDIT----------------------

    I'm also having a little trouble getting my script to actually grab the item at the point where my controller is touching/grabbing the item.

    If I grab the item at it's side. It'll move so the middle of the item is at my controller.
     
    Last edited: Oct 27, 2016