Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 14 Next capture
2021 2022 2023
2 captures
13 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 /
avatar image
0
Question by Juice-Tin · Nov 11, 2021 at 03:40 PM · quaternioneasing

Ease out a Quaternion?

Hello, I have some code to ease out variables over time, for example:

 source += (target - source) * deltaSpeed;


This will slowly move a source towards the target, by adding small amount of the required distance each frame (difference between target/source x speed)

The question is how do I replicate this with a quaternion? I've tried this, multiplying target by the inverse of source to replicate subtraction, using slerp to replicate multiplying it by speed, and then multiplying the entire thing to replicate adding it back to source.

 source = source * Quaternion.Slerp(Quaternion.identity, target * Quaternion.Inverse(source), deltaSpeed);


However that makes it go in wild directions. Any ideas how to do this properly? Thanks! (P.s. how do I make my newlines/spaces show up here?

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

Answer by bdubbert · Nov 11, 2021 at 04:14 PM

I think you misunderstand what Slerp does...


Slerp stands for Spherical Interpolation, which is just the spherical version of Lerp, which stands for linear interpolation. Lerp is pretty simple; given arguments a, b, and c choose a point between a and b where this point is the same distance between a and b that c is between 0 and 1. So Lerp(2, 12, 0.5) = 7. You can use Lerp for a kind of "Easing in" to a number by feeding back the result:

 float value = 0;
 
 void Update(){
     value = Lerp(value, 10, speed * Time.deltaTime);
 }
 

This code will make value approach 10 quickly at first, then slower as it gets closer to 10. That means that you could replace your top code snippet with source = Lerp(source, target, speed*Time.deltaTime); and have the same effect.


So, with Slerp, we can do the exact same thing for quaternions. Nothing fancy required.

 source = Quaternion.Slerp(source, target, speed * Time.deltaTime);

Which will ease you into the target rotation from the source rotation.

Comment
Add comment · Show 4 · 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 Juice-Tin · Nov 15, 2021 at 04:57 AM 0
Share

Excellent, thankyou for both the detailed explanation and solution.

avatar image Pangamini · Nov 15, 2021 at 09:30 AM 0
Share

While your answer is logically correct ( because the question was "how to do this but with Quaternions), It's technically very incorrect, just like the OP's original solution. That's the worst misconception that spreads through the Unity community probably since its beginning like a plague. I don't know where did it come from. Anyway, this has been discussed so many times already. Using deltaTime as lerp's proportion will lead to framerate-dependent behaviour, often very jerky, if the FPS is not stable. It will never reach its target (if FPS is over 1), it will approach the target with a varying speed (being slower with higher FPS), and will, of course, reach the target precisely in one frame if there's a lag that causes this frame's deltaTime to be longer than one second. Furthermore, you are using a value with unit of seconds in a unitless parameter of proportion.

avatar image unity_ek98vnTRplGj8Q Pangamini · Nov 15, 2021 at 03:07 PM 0
Share

So is there a better way to do this? Because not using deltaTime will most certainly lead to framerate dependant behavior as well. Using deltaTime at least gives a closer approximation, does it not?

avatar image Pangamini unity_ek98vnTRplGj8Q · Nov 15, 2021 at 04:51 PM 0
Share

I tried to explain some of it in the answer below

avatar image
0

Answer by Pangamini · Nov 15, 2021 at 04:51 PM

How do you define the rate of your motion / rotation in such case? Let's say: "In every second, I want the object to pass some portion P of its remaining distance". Then, if your framerate was simply 1, then your deltaTime would be 1. Then all you'd need to do would be to multiply the remaining distance by portion P (which is a value between 0 and 1). This, using the unity's Slerp, would be written as follows:

transform.rotation = Quaternion.Slerp(transform.rotation, targetRotation, P);

Slerp is a bit more complicated by itself, so let's rewrite the whole problem to linear motion and Lerps:

 transform.position = Vector3.Lerp(transform.position, targetPosition, P);

Which could be rewritten as:

 Vector3 remaining = targetPosition - transform.position;
 transform.position += remaining * P;

The key thing to note here is this: We are multiplying the remaining distance by some unitless value that ranges from 0 to 1. The only problem remains, that the FPS is practically never exactly one (that would be a really bad game, really) and we need to recalculate the new portion, adequate to the actual delta time. Now, the popular mistake is that we simply multiply the portion by deltaTime. That's going to slow the progress down as the FPS increases. That statement itself is true, but let's see if that works. Let's change FPS to 2. That makes our deltaTime equal 0.5. We now multiply our remaining distance by some value twice as often. We need to make sure, that after two multiplications (in 2 FPS instead of 1 FPS) we end up with the same value. Let's say we want to pass 90% of the remaining distance in a second. That's multiplying by 0.9 every second. That's NOT multiplying by 0.9 * 0.5 (our deltaTime) twice. That would equal approximately 0.2, which is very far from the original value. We instead want to make sure that two multiplications over two frames give us a total multiplier of 0.9. And that multiplier, of course, equals the square root of 0.9. Now, we need to expand this solution to any FPS. Our root won't be square, but the FPS. And we end up with something like this:

 float t = 1-Mathf.Pow(1-beta, deltaTime);
 transform.rotation = Quaternion.Slerp(transform.rotation, targetRotation, t);

where beta is how much of the distance is passed every second. Change 1-beta to beta, to describe how much of the distance is passed every second. Notice that I've switched back to using quaternions and slerp. It's because we are calculating the proportion in relation to the time, and we don't really care what it is used for.

Edit: I feel like I skipped some steps in my thoughts and math. Just ask if anything is unclear

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 bdubbert · Nov 15, 2021 at 07:58 PM 0
Share

Very cool, this is not something that I've seen before but makes a lot of sense. Thanks for your reply.

avatar image Pangamini bdubbert · Nov 15, 2021 at 11:17 PM 0
Share

I've just read my answer after 6 hours, and I am not sure if I'd be able to understand my own words there. Anyway, the code works, I've tested that with multiple instances running at different framerates. Spread the word, kill the virus

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

134 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 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

Rotation Ease-In-Out with MAX Rotation Speed 1 Answer

How to get a line parallel to a plane? 1 Answer

How to get angular difference? 2 Answers

Align plane to normal but keep Y-axis intact 1 Answer

Quaternion.Euler tilts rotation on z axis, even though the z rotation is set to 0 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