Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Question Apply local rotation from one object to another object in VR

Discussion in 'VR' started by jfbennai, Sep 11, 2020.

  1. jfbennai

    jfbennai

    Joined:
    Feb 26, 2020
    Posts:
    5
    Hello,
    I'm trying to implement a simple action in VR with SteamVR framework.
    The action is as simple as unscrew a screw with a tool attached to the VR hand.
    To do this, all I want to do is match the localRotation parameter of the screw to the localRotation of the tip of the tool (it has an empty object with the script which does this function each frame in OnTriggerStay).
    But I can't even make the screw rotate.
    I'm trying to use this script (it is placed in the empty GameObject in the tip of the tool):

    Code (CSharp):
    1. void RotateTool(GameObject screw)
    2.     {
    3. Vector3 eulerRotation = new Vector3(this.transform.localEulerAngles.z, screw.transform.localEulerAngles.y , screw.transform.localEulerAngles.z);
    4.    
    5. screw.transform.localRotation = Quaternion.Euler(eulerRotation);
    6.  
    7. }

    I've also tried to implement this by creating a new Quaternion like this:

    Code (CSharp):
    1. Quaternion newRot = Quaternion.Euler(0, 0, this.transform.localRotation.z);
    2. screw.transform.localRotation = newRot;

    It won't work either.
    Please, I would appreciate any help :)
     
    Last edited: Sep 14, 2020
  2. MattFS

    MattFS

    Joined:
    Jul 14, 2009
    Posts:
    219
    When you say it won't work... do you mean nothing at all happens?

    Some other options you could try:
    - Record the starting rotation as the tool activates, then rotate the screw by the difference of the tool.z - toolStart.z
    - Depending how many more tools and the complexity, perhaps check out the animation rigging package and have a look at it's constraints, it has some examples that could be used for what it seems you're trying to achieve
     
  3. jfbennai

    jfbennai

    Joined:
    Feb 26, 2020
    Posts:
    5
    Hi, thanks for the answer :)

    What happens with my actual code is only a sudden rotation of the screw in the wrong axis.
    The screw doesn't have any constraints in its Rigidbody, but it also happens when I apply them.
    I think I'm going to give your first option a try, sounds good to me.

    I've also tried to implement a SteamVR Circular Drive script on the screws, but making the tool have the hand mechanics is a pain.

    I don't want to add animations to the screws because of the project requirements.
    If somebody else has suggestions, they're welcome :)
     
  4. jfbennai

    jfbennai

    Joined:
    Feb 26, 2020
    Posts:
    5
    Update:

    I've managed to apply rotation to the screw by trying to calculate the difference between its localRotation among the actual frame and the previous one (Quaternion.Angle).
    As a result, the screw rotates, but I can´t seem to calculate the angle properly, because the screw always rotates in clockwise direction.

    I'm using this (RotateTool is called in OnTriggerStay when the tool touches the screw):

    Code (CSharp):
    1.  
    2.  
    3. Quaternion newRot;
    4. Quaternion prevFrame;
    5.  
    6.  
    7. private void Start()
    8.     {
    9.         prevFrame = Quaternion.identity;
    10.         newRot = prevFrame;
    11.      
    12.     }
    13.  
    14. void RotateTool(GameObject screw)
    15.     {
    16.    
    17.         Quaternion prevRot = Quaternion.Euler(new Vector3(0, 0, prevFrame.z));
    18.         Quaternion actualRot = Quaternion.Euler(new Vector3(0, 0, this.transform.rotation.z));;
    19.      
    20.  
    21.         if (Quaternion.Angle(prevRot,actualRot) > 0)
    22.         {
    23.             screw.transform.Rotate(Vector3.right, Space.Self);
    24.  
    25.         }
    26.  
    27.         else
    28.         {
    29.  
    30.             screw.transform.Rotate(-Vector3.right, Space.Self);
    31.         }
    32.  
    33.         prevFrame = this.transform.rotation;
    34.  
    35.     }
    Any hints on how to calculate the difference between rotations (in one or more axis)?
     
  5. jfbennai

    jfbennai

    Joined:
    Feb 26, 2020
    Posts:
    5
    Update:
    If someone is interested, I managed to solve this problem:
    The rotation of the screw is a bit messed because it is extremely responsive to the rotation of the controller, but it rotates accordingly (X axis of the screw rotates with the Z axis of the controller):

    Code (CSharp):
    1.  
    2. bool isIn;
    3. bool isOut;
    4. GameObject screwPto;
    5. Quaternion newRot;
    6. Quaternion prevFrame;
    7. public float screwRotMultiplier = 5f;
    8. public float stopOffset = 10f;
    9. public float screwSpeed = 0.01f;
    10.  
    11.  
    12.  
    13. private void Start()
    14.     {
    15.         prevFrame = Quaternion.identity;
    16.         newRot = prevFrame;
    17.         isIn = true;
    18.         isOut = false;
    19.  
    20.     }
    21.  
    22. void RotateTool(GameObject screw)
    23.     {
    24.    
    25.         Quaternion prevRot = Quaternion.Euler(new Vector3(prevFrame.eulerAngles.z, 0, 0));
    26.         Quaternion actualRot = Quaternion.Euler(new Vector3(this.transform.rotation.eulerAngles.z, 0, 0)); ;
    27.  
    28.         float normPrevRot = prevRot.eulerAngles.x;
    29.         normPrevRot /= 360;
    30.  
    31.         float normActualRot = actualRot.eulerAngles.x;
    32.         normActualRot /= 360;
    33.  
    34.         //If there is no rotation, only the Time counter is reset
    35.         if (normPrevRot == normActualRot + stopOffset || normPrevRot == normActualRot - stopOffset &&
    36.             counter >= maxTime)
    37.         {
    38.             counter = 0f;
    39.         }
    40.  
    41.         //PULL IN
    42.         if (screw.GetComponent<ScrewRotating>().GetDistanceTravelled() >= 0)
    43.         {
    44.             if (normPrevRot < normActualRot - stopOffset && counter >= maxTime)
    45.             {
    46.                 screw.transform.Rotate(-Vector3.right * screwRotMultiplier, Space.Self);
    47.                 screw.transform.Translate(Vector3.right * screwSpeed, Space.Self);
    48.  
    49.                 screw.GetComponent<ScrewRotating>().SetDistanceTravelled(-screwSpeed);
    50.  
    51.  
    52.                 counter = 0f;
    53.  
    54.            
    55.             }
    56.         }
    57.  
    58.         //PULL OUT
    59.         if (screw.GetComponent<ScrewRotating>().GetDistanceTravelled() <= (screw.GetComponent<Disassembly>().GetScrewLenght()))
    60.         {
    61.             if (normPrevRot > normActualRot + stopOffset && counter >= maxTime)
    62.             {
    63.  
    64.                 screw.transform.Rotate(Vector3.right * screwRotMultiplier, Space.Self);
    65.                 screw.transform.Translate(-Vector3.right * screwSpeed, Space.Self);
    66.  
    67.                 screw.GetComponent<ScrewRotating>().SetDistanceTravelled(screwSpeed);
    68.  
    69.                 counter = 0f;
    70.  
    71.  
    72.             }
    73.         }
    74.  
    75.  
    76.         //SCREW IN CHECK
    77.         if (screw.GetComponent<ScrewRotating>().GetDistanceTravelled() < (screw.GetComponent<Disassembly>().GetScrewLenght()) &&
    78.             !isIn &&
    79.             isOut)
    80.         {
    81.             screw.GetComponent<Disassembly>().AssemblyScrew();
    82.             isIn = true;
    83.             isOut = false;
    84.         }
    85.  
    86.         //SCREW OUT CHECK
    87.         if (screw.GetComponent<ScrewRotating>().GetDistanceTravelled() >= (screw.GetComponent<Disassembly>().GetScrewLenght()) &&
    88.         !isOut &&
    89.         isIn)
    90.         {
    91.             screw.GetComponent<Disassembly>().DisassemblyScrew();
    92.             isOut = true;
    93.             isIn = false;
    94.         }
    95.  
    96.  
    97.         prevFrame = this.transform.rotation;
    98.  
    99.  
    100.     }

    Mods, you can close this thread if you please. Thanks for the help :)
     
    Last edited: Sep 18, 2020
    dsmartin1 likes this.
  6. MattFS

    MattFS

    Joined:
    Jul 14, 2009
    Posts:
    219
    Glad you got it to work!

    You could also look at Quaternion.FromToRotation , which is the rotation difference between two vectors/directions, that would account for all axis' .
     
    jfbennai likes this.
  7. jfbennai

    jfbennai

    Joined:
    Feb 26, 2020
    Posts:
    5
    I've talked high too soon.
    Sadly I've checked that my code doesn't work unless you have a vertical screw and the screwdriver is upside down :(

    This is due to I'm getting global rotation of the screwdriver and comparing it from one frame to the next one, but I don´t know any other way of getting a value from its Z axis (local) when it rotates (and it needs to be a constant because the screwdriver can be in any position/rotation.


    I will try to work with this, thanks pal.
     
  8. PareshMasram

    PareshMasram

    Joined:
    Feb 19, 2022
    Posts:
    1
    Did you get the solution brother ??