Search Unity

Resolved Rotation around center by grabbing and pulling

Discussion in 'VR' started by ConnorBaltich, Mar 8, 2020.

  1. ConnorBaltich

    ConnorBaltich

    Joined:
    Nov 4, 2016
    Posts:
    10
    I need to create a way to rotate an object around its center by grabbing and pulling. It needs to work when facing in any direction whether you are behind the object or on a side of it.

    I want it to work similar to this video, but with grabbing and pulling in the air (does not have to be in contact with the object, or it can it doesn't matter to me).



    Any ideas on how to script this, I don't want to import any OVR assets that might interfere with the custom grabbing I have already created.

    Thanks in advance!

    I'm using the Oculus rift headset and the OVR API.
     
  2. JoeStrout

    JoeStrout

    Joined:
    Jan 14, 2011
    Posts:
    9,859
    When the trigger is pressed, calculate the nearest point on the sphere around the object (by just finding the vector between the controller position and the center, and then normalizing). Also store the orientation of the object at that point in some handy Quaternion property.

    Then on every frame while the trigger is down, again find the nearest point on the sphere. Now use Quaternion.FromToRotation to calculate the rotation between the original point and the new one. Finally, multiply that by the original (stored) orientation of the object to find the new rotation.
     
    jiraphatK likes this.
  3. ConnorBaltich

    ConnorBaltich

    Joined:
    Nov 4, 2016
    Posts:
    10
    Thanks! Worked flawlessly!

    Heres my code in case anyone is interested. Feel free to clean it up if you see a better way to do things!

    Code (CSharp):
    1. [Header("Controller")]
    2.     public OVRInput.Button grabButton;
    3.     public OVRInput.Button resetRotationButton;
    4.  
    5.     [Header("Robot")]
    6.     public GameObject robot;
    7.  
    8.     [Header("Activation Settings")]
    9.     public float activationDistance;
    10.  
    11.     private Quaternion currentRot;
    12.     private Vector3 startPos;
    13.     private bool offsetSet;
    14.  
    15.     private void Start()
    16.     {
    17.         offsetSet = false;
    18.     }
    19.  
    20.     // Update is called once per frame
    21.     void Update()
    22.     {
    23.         if (OVRInput.Get(grabButton) && IsCloseEnough())
    24.             Rotate();
    25.         else
    26.             offsetSet = false;
    27.  
    28.         if (OVRInput.GetDown(resetRotationButton))
    29.             robot.transform.eulerAngles = Vector3.zero;
    30.     }
    31.  
    32.     void SetOffsets()
    33.     {
    34.         if (offsetSet)
    35.             return;
    36.  
    37.         startPos = Vector3.Normalize(transform.position - robot.transform.position);
    38.         currentRot = robot.transform.rotation;
    39.  
    40.         offsetSet = true;
    41.     }
    42.  
    43.     void Rotate()
    44.     {
    45.         SetOffsets();
    46.  
    47.         Vector3 closestPoint = Vector3.Normalize(transform.position - robot.transform.position);
    48.         robot.transform.rotation = Quaternion.FromToRotation(startPos, closestPoint) * currentRot;
    49.     }
    50.  
    51.     bool IsCloseEnough()
    52.     {
    53.         if (Mathf.Abs(Vector3.Distance(transform.position, robot.transform.position)) < activationDistance)
    54.             return true;
    55.  
    56.         return false;
    57.     }
     
  4. saifshk17

    saifshk17

    Joined:
    Dec 4, 2016
    Posts:
    488
    Hey thanks for this!
    How do I use it only for y axis?
     
  5. JoeStrout

    JoeStrout

    Joined:
    Jan 14, 2011
    Posts:
    9,859
    You could take the result of that Quaternion.FromToRotation call, and use Quaternion.FromEulerAngles to create a new quaternion from only the Y component of that.

    Or, you could ditch the fancy quaternion stuff and just use Mathf.Atan2 to calculate the angle you need to rotate around the Y axis (giving it the X and Z differences between the old point and the new point).
     
  6. saifshk17

    saifshk17

    Joined:
    Dec 4, 2016
    Posts:
    488
    Sorry I am still not able to freeze the x and z rotation from the above script. Can you please edit it?
     
  7. JoeStrout

    JoeStrout

    Joined:
    Jan 14, 2011
    Posts:
    9,859
    Try replacing line 48 with:

    Code (csharp):
    1. var rot = Quaternion.FromToRotation(startPos, closestPoint);
    2. rot = Quaternion.Euler(0, rot.eulerAngles.y, 0);
    3. robot.transform.rotation = rot * currentRot;
     
    saifshk17 likes this.
  8. saifshk17

    saifshk17

    Joined:
    Dec 4, 2016
    Posts:
    488
    Perfect! Works really well. Thank you for this :)
     
    JoeStrout likes this.
  9. saifshk17

    saifshk17

    Joined:
    Dec 4, 2016
    Posts:
    488

    Remove the "{" in line 20.
     
    sparkoflife10 likes this.
  10. sparkoflife10

    sparkoflife10

    Joined:
    Jan 14, 2021
    Posts:
    1
    I have a doubt, I need to rotate the object by grabbing it. Should I attach this script to the GameObject?
     
  11. saifshk17

    saifshk17

    Joined:
    Dec 4, 2016
    Posts:
    488
    Attach this script to the object (plane, cube, etc. 3D model) for which the object should be rotated. The robot in this script means 3D model and the user rotates the robot in this context.
     
  12. Indu_Saikumar

    Indu_Saikumar

    Joined:
    Feb 12, 2021
    Posts:
    1
    Hello, thanks for the reply. Could you please help me a bit more, I'm unable to rotate the object. Grab button and Reset rotation button should be set to which buttons of the controller?
     

    Attached Files: