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
0
Question by phxvyper · Oct 14, 2013 at 06:34 AM · c#quaternionslerp

Slerp Rotation Problem

I'm experiencing an issue with Quaternion.Slerp

Click this to watch: This video shows whats occurring with the game.

Here is the code im having an issue with:

 public Vector3 newBreakerRotation = new Vector3(0, 0, 0);
 public bool bRotating;
 public float preRotate;
 public float BreakerRotSpeed = 5f;
 
 void Start() {
     newBreakerRotation = transform.eulerAngles;
 }
 
 void Update() {
     float rotate = Input.GetAxis("Rotate");
     
     if (!bRotating) {
         if ((rotate > 0f || rotate < 0f) && rotate != preRotate) {
             //Code that manipulates the value of newBreakerRotation.
             //If Q is pressed, the rotation's z axis is decreased by 90.
             //If E is pressed, the rotation's z axis is increased by 90.
             bRotating = true;
         }
     }
     
     if (transform.eulerAngles != newBreakerRotation) {
         transform.rotation = Quaternion.Slerp(transform.rotation, Quaternion.Euler(newBreakerRotation), BreakerRotSpeed * Time.deltaTime);
     }
     else {
         bRotating = false; // This never gets called. Why?
     }
 }

Why doesn't bRotating = false; get called ever?

Thank you!

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 Hoeloe · Oct 14, 2013 at 06:49 AM

Equality testing with floating point arithmetic is always a bad idea. Floating point values (that's anything marked float or double, including the fields of Vectors and Quaternions) are notoriously inaccurate. Because of the way they are represented in the computer, they accumulate errors over time. These errors are usually not noticeable, but they do cause equality testing to fail. For example, you might be testing if a number is equal to 0.5, but over time, the errors accumulated means the number is actually 4.9999998721. This difference is so small it is unnoticeable to the naked eye, but these two values are not equal, so equality testing will fail.

So, what can you do to solve this? Well, it's actually quite simple - use a margin of error, instead of an equality test. So rather than writing:

 transform.eulerAngles != newBreakerRotation

Try something like this:

 (transform.eulerAngles - newBreakerRotation).sqrMagnitude > 0.0001f

(Note that I'm using the square of the magnitude here, not the magnitude, for performance reasons - it saves on a costly square root call.)

You can tweak the value 0.0001f however you like. The smaller it is, the more accurate your results will be, but making it too small will cause your issue to reoccur. Making it larger will cause your rotation to stop early, but a value like 0.0001, or even 0.001, should be sufficient for good results. If you really want to to be accurate, you can also add a clause to snap the rotation to the desired value once you detect the difference to be below the margin of error.

Comment
Add comment · Show 15 · 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 phxvyper · Oct 14, 2013 at 06:58 AM 0
Share

Thank you for your answer. However, did this and it did not resolve my issue. I played with the float value comparison against sqr$$anonymous$$agnitude, it didn't help.

Any other ideas?

avatar image meat5000 ♦ · Oct 14, 2013 at 08:38 AM 1
Share

Your code says this, line 14

if (rotate != preRotate && rotate != 0)

Edit: just in case you misconstrued, I waan't telling you to try this, I was saying it is the same as this. Adding this in just in case.

avatar image Hoeloe · Oct 14, 2013 at 09:22 AM 1
Share

Again, show your code.

avatar image Hoeloe · Oct 15, 2013 at 06:04 AM 1
Share

I did, but then I also told you to do the same for all floating point comparison, of which you still have 2 more: (rotate > 0f || rotate < 0f) and rotate != preRotate

avatar image Hoeloe · Oct 15, 2013 at 12:34 PM 1
Share

I feel I should point out that you STILL are using an equality check with floats, when checking rotate. The only reason this works correctly is because Unity has the margin of error built-in (to set the value to 0 if it's below a threshold), but it's worth noting that ANY floating point comparison (except in specific cases like this) should be done with a margin of error.

Show more comments
avatar image
0

Answer by meat5000 · Oct 14, 2013 at 07:55 AM

BreakerRotSpeed * Time.deltaTime

This term does not scale between 0 and 1 with time. Slerp will not slerp

Hoeloe is spot on in the reason why it never reaches the 'else'

Comment
Add comment · Show 8 · 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 Hoeloe · Oct 14, 2013 at 08:48 AM 0
Share

It will lerp, because the start value is changed every frame. It won't be slerp, strictly, as it will have extra easing, but it will work.

avatar image phxvyper · Oct 14, 2013 at 08:54 AM 0
Share

Can you elaborate on the scale thing?

avatar image meat5000 ♦ · Oct 14, 2013 at 09:14 AM 0
Share

I say scale as moving t between 0 and 1 scales the lerps return value between from and to.

Yep I see it now Hoeloe, urgh its one of those ^ ^

avatar image meat5000 ♦ · Oct 14, 2013 at 08:16 PM 0
Share

@Hoeloe Do you know of a particular term for using a Lerp function this way? It's Lerp but not as we know it. Care to coin one?

avatar image Hoeloe · Oct 14, 2013 at 08:25 PM 0
Share

I'd call it something like "Eased Lerp", "Smoothed Lerp" or "Exponential Lerp", since those all describe the effect you get quite nicely.

Show more comments

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

16 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

Related Questions

Quaternion Rotation Smooth 1 Answer

Multiple Cars not working 1 Answer

My Quaternion rotation happens instantly 0 Answers

Rotating Armature During Animation 1 Answer

Distribute terrain in zones 3 Answers


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