Search Unity

Rotating at a constant speed

Discussion in 'Scripting' started by rayanjiffri, Jan 9, 2013.

  1. rayanjiffri

    rayanjiffri

    Joined:
    Aug 22, 2012
    Posts:
    31
    Hello,

    I have recently been trying to rotate an object at a constant speed, but I failed to do so.

    You see the "LookAt" moves fast at first but as it begins to come closer to the designated rotation it slows down.

    Thank in advance
     
  2. Kortekk

    Kortekk

    Joined:
    Sep 25, 2009
    Posts:
    20
  3. rayanjiffri

    rayanjiffri

    Joined:
    Aug 22, 2012
    Posts:
    31
    Hello and thank you for replying,

    Yes I have tried that but you see what I'm trying to do is make it look at a moving object ( slowly, constant speed) But not rotating it using buttons/inputs.


    Is there a way to modify the look at so that it will not slow down before reaching the target ?
     
  4. Kortekk

    Kortekk

    Joined:
    Sep 25, 2009
    Posts:
    20
  5. CaptainKirby

    CaptainKirby

    Joined:
    Dec 12, 2011
    Posts:
    33
    LookAt should not be slowing down, it should be following the object constantly.
    Could you try and describe precisely what the function you wish to achieve is?
     
  6. sushanta1991

    sushanta1991

    Joined:
    Apr 3, 2011
    Posts:
    282
    try this
    Code (csharp):
    1.  
    2. transform.Rotate(0,10,0);
    3.  
     
    Laniemme likes this.
  7. Marrt

    Marrt

    Joined:
    Feb 7, 2012
    Posts:
    527
    Hi, i know exactly what you mean with constant rotation speed, i used this in my game to rotate at a constant rate towards my reticle (try the game in my signature to see it in action, press U to slow down time if it is to fast)

    just use:
    http://docs.unity3d.com/Documentation/ScriptReference/Quaternion.RotateTowards.html

    if you don't get any results respond, i can post my code in ~8hours when i get home from work...

    EDIT:
    -a nice little trick for constant speed is using an empty gameObject(just for having a transform) rotating around another gameObject that uses LookAt to look at the empty gameObject
    -or http://docs.unity3d.com/Documentation/ScriptReference/Transform.RotateAround.html using the position of itself
     
    Last edited: Jan 10, 2013
  8. rayanjiffri

    rayanjiffri

    Joined:
    Aug 22, 2012
    Posts:
    31
    Thank you for replying gentlemen.


    Mart... You do really understand my problem.

    You see theres a turret. A pivot in it and some empty transform 3 meters in front of it . The empty transform rotates AROUND THE PIVOT that is in the turret. And the turret turns toward the transform that is 3Meters in front of the pivot.

    World of Tanks players ( Not advertising or anything!!! ) would understand like you mart .but it looks like someone has the same issue as me . :)

    I will try your suggestion as soon as I get home from school..


    Thank you.
     
  9. rayanjiffri

    rayanjiffri

    Joined:
    Aug 22, 2012
    Posts:
    31
    Ok, so I have tried to do what you mentioned above , but I couldn't figure out how to "Get It To Work". Please be patient with me, I'm not much of a proggramer/scripter .
     
  10. Marrt

    Marrt

    Joined:
    Feb 7, 2012
    Posts:
    527
    This is my solution, it allows to cap the rotation speed to a certain amount of degree/s, call it every Update:

    Code (csharp):
    1. private void ShipRotationLimited(){
    2. //LIMITED Rotation caused by Movement of Reticle
    3.     Quaternion limitedRotation = new Quaternion(0F,0F,0F,0F);      
    4.     Quaternion rotation = Quaternion.LookRotation(rt.reticleOrigin - thisTransform.position);
    5.     //lock rotation, yaw only
    6.     rotation.eulerAngles = new Vector3(0,rotation.eulerAngles.y,0);
    7.    
    8.     //rotates the Ship to Reticle with fixed speed
    9.     limitedRotation = Quaternion.RotateTowards(thisTransform.rotation, rotation, degsPerSec * Time.deltaTime);
    10.    
    11.     thisTransform.rotation = limitedRotation;
    12. }
    if you need a unlimited offsetRotation like i do in my game for recoil (rotations caused by recoil are not capped by my degsPerSec)

    Code (csharp):
    1. private void ShipRotation(){
    2. //Using Model as rotation origin
    3. //LIMITED Rotation caused by Movement of Reticle
    4.     Quaternion limitedRotation = new Quaternion(0F,0F,0F,0F);      
    5.     Quaternion rotation = Quaternion.LookRotation(rt.reticleOrigin - shipModelTransform.position);
    6.     //lock rotation, yaw only
    7.     rotation.eulerAngles = new Vector3(0,rotation.eulerAngles.y,0);
    8.    
    9.     //rotates the Ship to Reticle with fixed speed
    10.     limitedRotation = Quaternion.RotateTowards(lastLimitedRotation, rotation, degsPerSec * Time.deltaTime);
    11.     lastLimitedRotation = limitedRotation; //save limitedRotation for next frame
    12.    
    13. //UNLIMITED rotation caused by Recoil: 
    14.     //independently from maxDegree/s rotate additionaly by the recoil and add it to the limited rotation
    15.     //this makes rotations caused by recoil independent from the maxRot/s
    16.     //so this should behave like an maxDeg/s-indepenent rotation Offset!
    17.     Quaternion unlimitedRotation = new Quaternion(0F,0F,0F,0F);
    18.     //calculate Angle Difference
    19.     Quaternion shipToGhostReticleRotation   = Quaternion.LookRotation(rt.ghostReticleOrigin - thisTransform.position);
    20.     Quaternion shipToReticleRotation        = Quaternion.LookRotation(rt.reticleOrigin - thisTransform.position);
    21.     unlimitedRotation = Quaternion.Inverse(shipToReticleRotation) *shipToGhostReticleRotation;     
    22.                            
    23. //APPLY the combined Rotation (addition of 2 quats is done by mutliplying them, subtraction by multiplying the inverse)
    24.     thisTransform.rotation = limitedRotation * unlimitedRotation;
    25. }
    Description:
    -This Function is Called Every Update()
    -it rotates my ship (shipModelTransform) with a constant speed (degsPerSec) to my reticleOrigin (rt.reticleOrigin, this is a position so you have to put a Vector 3 in there)
    -but this rotation is only applied for the y-axis, check the axis you need, the y axis is the axis parallel to gravity

    Unlimited Rotation:
    -The unlimited Rotation offsets the Rotation making the ship point to a recoil reticle which can be moved with infinite speed to simulate recoil (very nice effect for better shooting experience for a top down shooter)
    -to use it you have to have another position (rt.ghostReticleOrigin)
    -this position should be the reticle's position + a recoilVector that grows when shooting and decreases over time (just look at my game in the signature, the recoil affected reticle is the ghostreticle)
     
    Last edited: Jan 11, 2013
  11. rayanjiffri

    rayanjiffri

    Joined:
    Aug 22, 2012
    Posts:
    31
    Thanks for Replying Maart,

    You're soloution is a bit "Advanced" for a novice like me. i do not really have much knowledge about C#. Perhaps you can point out the important part from the code that limits the rotation speed ?

    Thank you
     
  12. Marrt

    Marrt

    Joined:
    Feb 7, 2012
    Posts:
    527
    yeah ,just edited the post since i found a way to improve my script now, just use the first box and you should be fine:

    thisTransform.rotation -> your turret that has to rotate, e.g. this could be: myTurret.transform.rotation
    rt.reticleOrigin -> your position you want to target, e.g. this could be: myReticle.transform.position or your cursor position with cam.ScreenPointToRay(Input.mousePosition).GetPoint(cam.position.y); //getPoint gets a specific distance to the camera
     
  13. sixteenbits

    sixteenbits

    Joined:
    Jan 11, 2013
    Posts:
    2
    .
     
    Last edited: Jan 12, 2013
  14. bigmisterb

    bigmisterb

    Joined:
    Nov 6, 2010
    Posts:
    4,221
    erm... All this is fine and dandy, there is a simple way to do this: Use the target position to find the rotation point of the turret by swapping that location to the local space, then setting it's Y to zero, then back to world space. Next, store the current rotation, do a LookAt with the turret, using it's Up vector. Now, do a Quaternion.RotateTowards using the orignal rotation, the look rotation and the traverse speed times the deltaTime.

    Code (csharp):
    1.  
    2. var turretTraverseSpeed:float = 40;
    3. function MoveTurret(target:Transform){MoveTurret(target.position);}
    4. function MoveTurret(target:Vector3){
    5.     var lookAt:Vector3 = transform.InverseTransformPoint(target);
    6.     lookAt.y = 0;
    7.     lookAt = transform.TransformPoint(lookAt);
    8.    
    9.     var rotation:Quaternion = transform.rotation;
    10.     transform.LookAt(lookAt, transform.up);
    11.     var lookRotation:Quaternion = transform.rotation;
    12.     transform.rotation = Quaternion.RotateTowards(rotation, lookRotation, turretTraverseSpeed * Time.deltaTime);
    13. }
    14.  

    http://docs.unity3d.com/Documentation/ScriptReference/Quaternion.RotateTowards.html
     
  15. Marrt

    Marrt

    Joined:
    Feb 7, 2012
    Posts:
    527
    not that obvious but for sure easier than my approach :D

    question: does that "lookAt.y = 0;" generate more instructions in background? since in c# i am not allowed to set the y of a Vector directly (always have to assign the whole vector)

    since i asked the above, i always wondered what LookAt() does in background, is it cheaper than LookRotation?

    just curious, maybe you know
     
  16. bigmisterb

    bigmisterb

    Joined:
    Nov 6, 2010
    Posts:
    4,221
    LookAt is fairly cheap. Though I am not the Quaternion master here.

    The lookAt.y is a generic Vector3 assignment. Notice that lookAt was created on the line previous. It has no real extra processing value or importance other than to make sure that the LooAt point is on the same plane as the turret. Using this you have no x rotation when you do the actual LookAt.

    At no point do I specifically set a position or rotation element here. So: transform.position.y = 3; is never done. (this can be done in US, but not in CS)

    LookRotation is a portion of LookAt, so obviously it is greater than the sum of LookRotation. How much more, I do not know. These are mathematical functions though. They are incredibly quick.

    You could always set up a test to see how much of an impact this has in the overall picture. (run it 10000 times in one frame and see if your frame rate drops.)
     
  17. Marrt

    Marrt

    Joined:
    Feb 7, 2012
    Posts:
    527
    Ahh thanks for the hint with the test case! never thought of just testing performance myself XD
     
  18. DanielQuick

    DanielQuick

    Joined:
    Dec 31, 2010
    Posts:
    3,137
    Code (csharp):
    1.  
    2. lookAt.y = 0;
    3.  
    Is equivalent in performance to
    Code (csharp):
    1.  
    2. lookAt = new Vector3 (lookAt.x, 0, lookAt.z);
    3.  
     
    Last edited: Jan 11, 2013
  19. rayanjiffri

    rayanjiffri

    Joined:
    Aug 22, 2012
    Posts:
    31
    Thank you gentlemen,

    I will try to put your suggestions in my game and see how it works.

    I will reply if I have any issues but at the moment i appreciate the help

    Thanks guys.


    EDIT: Worked like a charm... I dont know what to say.

    Thank you bigmisterb, Marrt and all who tried to help.
     
    Last edited: Jan 13, 2013