Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 13 Next capture
2021 2022 2023
1 capture
13 Jun 22 - 13 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 /
avatar image
1
Question by AntLewis · Dec 16, 2011 at 10:32 AM · quaternioncoroutine

Quaternion.Slerp in a coroutine

Hi, I'm having an issue with the timing of a rotation. I have a coroutine which translates an object and at the same time I want to rotate it smoothly for as long as it's moving.

     public IEnumerator MoveToPosition (Vector3 newLocalTarget, float time)
 {
     float elapsedTime = 0.0f;
     Vector3 startingPosition = transform.localPosition;

     Quaternion targetRotation =  Quaternion.Euler ( new Vector3 ( 0.0f, 0.0f, 200.0f ) );
         
     while (elapsedTime < time) {
          transform.localPosition = Vector3.Lerp (startingPosition, newLocalTarget, (elapsedTime / time)   );    
         
         // Rotations
         transform.rotation = Quaternion.Slerp(transform.rotation, targetRotation,  (elapsedTime / time )  );
  
         elapsedTime += Time.deltaTime;
         yield return new WaitForEndOfFrame ();
     }
     Debug.Log ("Translation and rotation done! ");
     yield return 0;
 }

The translation works as expected. However, the rotation rotates to the desired angle, but finishes rotating around half the time it takes the object to translate. Ideally I want the rotation and translation to end at the same time. I've tried using Quaternion.Lerp in place, but the same problem exists. Can anyone spot the issue? Is there any other way so the rotation completes at the same time as the translation?

Many thanks

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
5
Best Answer

Answer by aldonaletto · Dec 16, 2011 at 12:21 PM

You should have a startingRotation variable to tell what's the initial rotation. You should also move the elapsedTime increment to the beginning of the while to ensure that the final position/rotation will be reached before the while ends:

    ...
    Vector3 startingPosition = transform.localPosition;
    Quaternion startingRotation = transform.rotation; // have a startingRotation as well
    Quaternion targetRotation =  Quaternion.Euler ( new Vector3 ( 0.0f, 0.0f, 200.0f ) );
    while (elapsedTime < time) {
       elapsedTime += Time.deltaTime; // <- move elapsedTime increment here
       transform.localPosition = Vector3.Lerp (startingPosition, newLocalTarget, (elapsedTime / time)   );  
       // Rotations
       transform.rotation = Quaternion.Slerp(startingRotation, targetRotation,  (elapsedTime / time)  );
       yield return new WaitForEndOfFrame ();
    }
    ...
NOTE: You're using localPosition, but not localRotation. Is this an intended feature? Mixing local and non-local position/rotation may give weird results.
Comment
Add comment · Show 2 · 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 AntLewis · Dec 16, 2011 at 01:35 PM 0
Share

Argh! Of course, right on all 3 counts (didn't mean to mix localposition and non local rotation). Thanks so much!

avatar image sarynth · Oct 03, 2020 at 04:18 PM 0
Share

This is still useful and works great. Another answer was using a damper variable in the last parameter of Slerp. Seeing this answer made Slerp make so much more sense. $$anonymous$$y character now rotates the entire direction I want in the exact time, adjusting speed to fit the time requirement. Thank you from 2020!

avatar image
0

Answer by leonardo_try · Dec 16, 2011 at 11:23 AM

try putting just the elapsedTime in the Lerp and Slerp instead of (elapsedTime / time) and to get a linear movement on the translation, use transform.localPosition where starting position is

Comment
Add comment · Show 2 · 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 AntLewis · Dec 16, 2011 at 11:41 AM 0
Share

Thanks for the response, but putting in elapsed time rather the elapsedTime/ time will just lock the movement to 1 second. Having (elapsedTime / time) allows me to specify a time for the movement.

avatar image Bunny83 · Dec 16, 2011 at 03:43 PM 1
Share

I don't want to offend you. I just want to clear up some facts. ;)

Generally there are two common uses of lerp. The first one is how it's ment to be used by giving a fix start and end point and move the t value slowly from 0 to 1. This will give you a true linear interpolation.

The second use of lerp is to do a decelerated movement by using the current position as start (which changes each time) and a small constant t value. This is what happens: If you use 0.2 as t value (just as example) It will move 20% of the remaining distance each step. Since the remaining distance will get smaller each frame the amount of movement is getting smaller which cause the slow-down effect. If you start at 100 and want to reach 0 it would be like this:

 frame,   current V,   remaining distance(RD),   20% of RD
     1          100                       100           20
     2           80                        80           16
     3           64                        64           12.8
     4           51.2                      51.2         10.24
     5           40.96                     40.96         8.19
     6           32.77                     32.77         6.55
  ...

Usually you multiply your constant with Time.deltaTime to be frame independend, but it doesn't really work. Example: If the above example is done at 1 frame per second (just as example) the delta time value would be 1.0 and you would get exact the result above.

But when you have 4 frames per sec (deltatime of 0.25) scaling down the t-constant linearly by 0.25 doesn't work as expected:

 frame,   current V,   remaining distance(RD),   20% of RD
     1          100                       100            5
     2           95                        95            4.75
     3           90.25                     90.25         4.5125
     4           85,7375                   85,7375       4.2869
     5           81,4506

So at 1 fps after 1 sec we have a value of 80. At 4 fps after the same time (1 sec == 4 frames) we have a value of 81.4. This "error" getting even worse when your frame rate gets higher. So as a result it will get faster when the framerate is lower.

If you want an accelerated / decelerated movement that happens in a specific time span, use a Hermite interpolation

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

7 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

How can you tell if a gameobject is looking directly at another gameobject? 1 Answer

Random smooth rotation on z-axis every other second 2 Answers

better way to rotate instead Coroutine 1 Answer

Coroutine While loop help 2 Answers

Coroutine with Quaternion.Angle 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