Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 14 Next capture
2021 2022 2023
2 captures
12 Jun 22 - 14 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 /
  • Help Room /
avatar image
0
Question by azinicus · Nov 08, 2016 at 12:10 AM · vrrotate objectquaternionscontrollers

VR Challenge: Rotation issue when holding object with both hand controllers vertically

When working with two VR controllers, there is a use case where when gripping (we've tried our own code - below - and VRTK to do this and both have the same logic problem) and rotating an object with both controllers, at the vertical position of the controllers the object will start unnaturally rotating on the y-axis (World Space). This is problematic if you want to have an experience where users are using two hands to move and rotate objects naturally. Here's a video of the issue in action.

Also the code that controls the rotation:

 using UnityEngine;
 using System.Collections;
 using VRTK;
  
 public class RotateControl : MonoBehaviour {
     VRTK_ControllerEvents events;
     VRTK_InteractGrab grab;
     public VRTK_InteractGrab analogGrab;
     GameObject lastTrigger;
  
     public bool rotating;
     Vector3 startPos;
     Vector3 startDiff;
     Vector3 diff;
     Vector3 d;
  
     // Use this for initialization
     void Start () {
         lastTrigger = gameObject;
         events = GetComponent<VRTK_ControllerEvents> ();
         grab = GetComponent<VRTK_InteractGrab> ();
         GetComponent<VRTK_ControllerEvents>().TriggerPressed += new ControllerInteractionEventHandler(DoTriggerPressed);
         GetComponent<VRTK_ControllerEvents>().TriggerReleased += new ControllerInteractionEventHandler(DoTriggerReleased);
  
     }
     private void DoTriggerPressed(object sender, ControllerInteractionEventArgs e)
     {
         if (GetComponent<VRTK_InteractTouch> ().touchedObject == null && analogGrab.GetGrabbedObject() != null) {
             startPos = transform.position;
             startDiff = analogGrab.transform.position - transform.position;
             rotating = true;
         }
     }
  
     private void DoTriggerReleased(object sender, ControllerInteractionEventArgs e)
     {
         if(rotating)
             rotating = false;
     }
     void Update()
     {
         if (rotating) {
             diff = analogGrab.transform.position - transform.position;
             d = diff - startDiff;
             if (Abs(startDiff.z) >= Abs(startDiff.x) && Abs(startDiff.z) >= Abs(startDiff.y)) 
             {
                 if (diff.z > 0 && d.z <= -1) 
                 {
                     if (d.x >= 1) 
                     {
                         analogGrab.GetGrabbedObject().transform.RotateAround(transform.position,Vector3.up, 90);
                         Debug.Log ("zp - Dreapta,  1");
                         startDiff = diff;
                     }
                     else
                         if(d.x <= -1)
                         {
                             analogGrab.GetGrabbedObject().transform.RotateAround(transform.position,Vector3.up, -90);
                             Debug.Log ("zp - Stanga,  2");
                             startDiff = diff;
                         }
                         else
                             if(d.y >= 1)
                             {
                                 analogGrab.GetGrabbedObject().transform.RotateAround(transform.position,Vector3.right, 90);
                                 Debug.Log ("zp - Sus,  3");
                                 startDiff = diff;
                             }
                             else
                                 if(d.y <= -1)
                                 {
                                     analogGrab.GetGrabbedObject().transform.RotateAround(transform.position,Vector3.right, -90);
                                     Debug.Log ("zp - Jos,  4");
                                     startDiff = diff;
                                 }
                                 else
                                     if(d.z <= -2 )
                                     {
                                         analogGrab.GetGrabbedObject().transform.RotateAround(transform.position,Vector3.up, 180);
                                         Debug.Log ("zp - 180,  5");
                                         startDiff = diff;
                                     }
                 } 
                 else if(diff.z < 0 && d.z >= 1)
                 {
                     if (d.x >= 1) 
                     {
                         Debug.Log ("zn - Dreapta,  1");
                         startDiff = diff;
                         analogGrab.GetGrabbedObject().transform.RotateAround(transform.position,Vector3.up, -90);
                     }
                     else
                         if(d.x <= -1)
                         {
                             analogGrab.GetGrabbedObject().transform.RotateAround(transform.position,Vector3.up, 90);
                             Debug.Log ("zn - Stanga,  2");
                             startDiff = diff;
                         }
                         else
                             if(d.y >= 1)
                             {
                                 analogGrab.GetGrabbedObject().transform.RotateAround(transform.position,Vector3.right, -90);
                                 Debug.Log ("zn - Sus,  3");
                                 startDiff = diff;
                             }
                             else
                                 if(d.y <= -1)
                                 {
                                     analogGrab.GetGrabbedObject().transform.RotateAround(transform.position,Vector3.right, 90);
                                     Debug.Log ("zn - Jos,  4");
                                     startDiff = diff;
                                 }
                                 else
                                     if(d.z >= 2 )
                                     {
                                         analogGrab.GetGrabbedObject().transform.RotateAround(transform.position,Vector3.up, 180);
                                         Debug.Log ("zn - 180,  5");
                                         startDiff = diff;
                                     }
                 }
             }
             else if (Abs(startDiff.x) >= Abs(startDiff.z) && Abs(startDiff.x) >= Abs(startDiff.y)) 
             {
                 if (diff.x > 0 && d.x <= -1) {
  
                     if (d.z >= 1) 
                     {
                         analogGrab.GetGrabbedObject().transform.RotateAround(transform.position,Vector3.up, 90);
                         Debug.Log ("xp - Dreapta,  1");
                         startDiff = diff;
                     }
                     else
                         if(d.z <= -1)
                         {
                             analogGrab.GetGrabbedObject().transform.RotateAround(transform.position,Vector3.up, -90);
                             Debug.Log ("xp - Stanga,  2");
                             startDiff = diff;
                         }
                         else
                             if(d.y >= 1)
                             {
                                 analogGrab.GetGrabbedObject().transform.RotateAround(transform.position,Vector3.forward, 90);
                                 Debug.Log ("xp - Sus,  3");
                                 startDiff = diff;
                             }
                             else
                                 if(d.y <= -1)
                                 {
                                     analogGrab.GetGrabbedObject().transform.RotateAround(transform.position,Vector3.forward, -90);
                                     Debug.Log ("xp - Jos,  4");
                                     startDiff = diff;
                                 }
                                 else
                                     if(d.x <= -2 )
                                     {
                                         analogGrab.GetGrabbedObject().transform.RotateAround(transform.position,Vector3.forward, 180);
                                         Debug.Log ("xp - 180,  5");
                                         startDiff = diff;
                                     }
                 } 
                 else if(diff.x < 0 && d.x >= 1)
                 {
                     if (d.z >= 1) 
                     {
                         analogGrab.GetGrabbedObject().transform.RotateAround(transform.position,Vector3.up, -90);
                         Debug.Log ("xn - Dreapta,  1");
                         startDiff = diff;
                     }
                     else
                         if(d.z <= -1)
                         {
                             analogGrab.GetGrabbedObject().transform.RotateAround(transform.position,Vector3.up, 90);
                             Debug.Log ("xn - Stanga,  2");
                             startDiff = diff;
                         }
                         else
                             if(d.y >= 1)
                             {
                                 analogGrab.GetGrabbedObject().transform.RotateAround(transform.position,Vector3.forward, -90);
                                 Debug.Log ("xn - Sus,  3");
                                 startDiff = diff;
                             }
                             else
                                 if(d.y <= -1)
                                 {
                                     analogGrab.GetGrabbedObject().transform.RotateAround(transform.position,Vector3.forward, 90);
                                     Debug.Log ("xn - Jos,  4");
                                     startDiff = diff;
                                 }
                                 else
                                     if(d.x >= 2 )
                                     {
                                         analogGrab.GetGrabbedObject().transform.RotateAround(transform.position,Vector3.forward, -180);
                                         Debug.Log ("xn - 180,  5");
                                         startDiff = diff;
                                     }
  
                 }
             }
             else if (Abs(startDiff.y) >= Abs(startDiff.z) && Abs(startDiff.y) >= Abs(startDiff.x)) 
             {
                 if (diff.y > 0 && d.y <= -1) {
                     if (d.x >= 1) 
                     {
                         analogGrab.GetGrabbedObject().transform.RotateAround(transform.position,Vector3.forward, -90);
                         Debug.Log ("yp - Dreapta,  1");
                         startDiff = diff;
                     }
                     else
                         if(d.x <= -1)
                         {
                             analogGrab.GetGrabbedObject().transform.RotateAround(transform.position,Vector3.forward, 90);
                             Debug.Log ("yp - Stanga,  2");
                             startDiff = diff;
                         }
                         else
                             if(d.z >= 1)
                             {
                                 analogGrab.GetGrabbedObject().transform.RotateAround(transform.position,Vector3.right, -90);
                                 Debug.Log ("yp - Sus,  3");
                                 startDiff = diff;
                             }
                             else
                                 if(d.z <= -1)
                                 {
                                     analogGrab.GetGrabbedObject().transform.RotateAround(transform.position,Vector3.right, 90);
                                     Debug.Log ("yp - Jos,  4");
                                     startDiff = diff;
                                 }
                                 else
                                     if(d.y <= -2 )
                                     {
                                         analogGrab.GetGrabbedObject().transform.RotateAround(transform.position,Vector3.right, 180);
                                         Debug.Log ("yp - 180,  5");
                                         startDiff = diff;
                                     }
  
                 } 
                 else if(diff.y < 0 && d.y >= 1)
                 {
                     if (d.x >= 1) 
                     {
                         analogGrab.GetGrabbedObject().transform.RotateAround(transform.position,Vector3.forward, 90);
                         Debug.Log ("yn - Dreapta,  1");
                         startDiff = diff;
                     }
                     else
                         if(d.x <= -1)
                         {
                             analogGrab.GetGrabbedObject().transform.RotateAround(transform.position,Vector3.forward, -90);
                             Debug.Log ("yn - Stanga,  2");
                             startDiff = diff;
                         }
                         else
                             if(d.z >= 1)
                             {
                                 analogGrab.GetGrabbedObject().transform.RotateAround(transform.position,Vector3.right, 90);
                                 Debug.Log ("yn - Sus,  3");
                                 startDiff = diff;
                             }
                             else
                                 if(d.z <= -1)
                                 {
                                     analogGrab.GetGrabbedObject().transform.RotateAround(transform.position,Vector3.right, -90);
                                     Debug.Log ("yn - Jos,  4");
                                     startDiff = diff;
                                 }
                                 else
                                     if(d.y >= 2 )
                                     {
                                         analogGrab.GetGrabbedObject().transform.RotateAround(transform.position,Vector3.right, -180);
                                         Debug.Log ("yn - 180,  5");
                                         startDiff = diff;
                                     }
  
                 }
             }
  
              
         }
     }
     float Abs(float f)
     {
         return Mathf.Abs (f);
     }
  
     void OnTriggerEnter(Collider coll)
     {
         //if (!changed && coll.tag == "RotCollider")// && grab.GetGrabbedObject () == null && analogGrab.GetGrabbedObject() != null && events.grabPressed ) 
         //{
             //changed = true;
             //lastTrigger = coll.gameObject;
             //analogGrab.GetGrabbedObject ().transform.LookAt (lastTrigger.transform.position);     
         //}
     }
     void OnTriggerExit(Collider coll)
     {
         //if (!changed && coll.tag == "RotCollider") {
         //  changed = false;
         //}
     }
  
 }

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
0

Answer by dyaroslavski · Jan 10, 2020 at 05:22 PM

I got this working correctly and the trick is that you want to keep applying the most recent rotation delta from each frame to your object's active transformation- NOT from your object's initial transformation at the time of "capture".

''

The fact that this is done in most two handed VR apps can be gleaned from testing rotations in a given order. Try it in your favorite VR app: start with two hands at the same Y some distance horizontally apart, then rotate them around Z 90 deg (as if you are turning a wheel) and then rotate them around X 90deg (as if you are wrapping something around your hands). Your resultant model orientation will be different than had you just rotated the model about Y 90 deg. This shows that the order of transformations matters, even if the final positions of your hands are at the same orientation from one another. This implies that you cannot create a single transformation algorithm that maps from initial positions & orientations to some active position & orientation.

''

I've found the solution requires applying three transformations:

''

First: multiply the rotation delta from the previous difference vector between the two hands and the new difference vector (in Unity, you can get this using Quaternion.FromToRotation). This will get you most of the way there.

''

Then, multiply your new orientation with two additional transformations representing the delta in rotation of each hand's orientation. I've found that this additional transformation should be scaled by half to get a good result (you can use Slerp of 0.5f from the default identity rotation) This gives you a sort of averaging of the influence of each of the two hands' orientations on the overall rotation.

''

Lastly, because the two hands orientation changes will modify the rotation angle of your model in a way that could "de-attach" the model from your hands, simply use a lookat function (in Unity, you can get this using Quaternion.LookRotation) with the resultant up vector of all these transforms as the up direction to get a final rotation (this essentially forces the rotation component applied from each hand to only influence the rotation about the axis between both hands).

''

This kind of algorithm will give you a realistic feeling rotation (with realistically changing up direction) and won't ever "jump" to a wildly different rotation (because you're constantly applying a rotation over time).

''

That said, you'll find that most 2-handed free-rotation algorithms exhibit some kinds of behavior that you may not find suitable with some movements(even in your favorite VR app) so the ideal solution will probably require additional thought to how you finally place your objects (snapping?) and if you want to limit rotation to a specific axis (It is possible -and easier- to create a consistent, completely order-independent transformation algorithm if you lock rotation to a single axis, say, Y).

''

Good luck!

Comment
Add comment · 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
0

Answer by alejo1099 · Nov 11, 2021 at 12:06 AM

https://github.com/alejo1099/Grabbing-Object-2-hands-VR I can resolve it, this work with one direction between two references points, and mantain the orientation, copy all after update method and write the conditions to activate it. Another thing, I don't read your code but I bet that do this

 TransformObjectToRotate.position = (TransformRightControl.position + TransformLeftControl.position) / 2;
 TransformObjectToRotate.LookAt (TransformRightControl);


Good luck ,https://github.com/alejo1099/Grabbing-Object-2-hands-VR I can resolve it, this work with one direction between two references points, and mantain the orientation, copy all after update method and write the conditions to activate it. Another thing, I don't read your code but I bet that do this TransformObjectToRotate.position = (TransformRightControl.position + TransformLeftControl.position) / 2; TransformObjectToRotate.LookAt (TransformRightControl); Good luck

Comment
Add comment · 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

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

94 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

Related Questions

Changing eye height with steamVR Camera Rig 2 Answers

How can I save spawned objects position in CSV? 1 Answer

how to map joystick for mobile game? 0 Answers

Beginner in C# - Simple Rotation Script 1 Answer

WMR in Unity using SteamVR No controllers showing 1 Answer


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