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 SelfishGenome · Feb 09, 2015 at 10:34 PM · rotationlerpsmoothslerpshmup

Slerp / lerp not creating a smooth transition

Hi all,

So I have an almost fully functional script utilising slerp to attempt to create a smooth veering movement for a shmup. But slerp and lerp seem to have no affect on the rotation and it will go from say 45 degrees straight back to 0 (leveled out).

I cannot see where I am going wrong. The entire script is below, if it helps to test it out, just stick it on a model in a scene and use the mouse and left click to move around.

Also, the first Slerp is controlling the ships veering motion from leveled out to the max rotation during movement, the second one at the bottom is from the max rotation back to leveling out. Neither are currently smooth.

 using UnityEngine;
 using System.Collections;
 
 public class PlayerController : MonoBehaviour
 {
     public float moveSpeed;                    
     public float rotSpeed;                    
     public float maxTilt;                    
 
     private Transform myTransform;                    
     private Vector3 destinationPoint;              
     private float destinationDistance;                
     public Vector3 defaultRotation;                 
 
     private GameObject Player;                     
 
     public bool hard = true;                        
 
     void Start()
     {
         myTransform = transform;                   
         destinationPoint = myTransform.position;    
 
         Player = GameObject.FindWithTag("Player");
       
     }
 
 
     void FixedUpdate()
     {
         destinationDistance = Vector3.Distance(destinationPoint, myTransform.position);
 
         if (Input.GetMouseButton(0))
         {
             Plane playerPlane = new Plane(Vector3.up, myTransform.position);
             Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
             float hitdist = 0.0f;
 
             if (playerPlane.Raycast(ray, out hitdist))
             {
                 Vector3 lastPosition = myTransform.position;
                 Vector3 targetPoint = ray.GetPoint(hitdist);
                 destinationPoint = ray.GetPoint(hitdist);
 
                 Vector3 D = targetPoint - transform.position;
 
                 Quaternion targetRotation = Quaternion.Slerp(transform.rotation, Quaternion.LookRotation(D), rotSpeed * Time.deltaTime);
 
                 myTransform.rotation = targetRotation;
 
                 if (targetPoint.x <= lastPosition.x)
                 {
                     transform.localEulerAngles = new Vector3(0, 0, transform.localEulerAngles.y + maxTilt);
                 }
                 else if (targetPoint.x >= lastPosition.x)
                 {
                     transform.localEulerAngles = new Vector3(0, 0, transform.localEulerAngles.y - maxTilt);
                 }
             }
         }
 
 
         if (destinationDistance > 0)
         {
             myTransform.position = Vector3.MoveTowards(myTransform.position, destinationPoint, moveSpeed * Time.deltaTime);
         }
         if (destinationDistance < 5f)
         {
             Quaternion playerRotation = myTransform.rotation;
             float rotationz = playerRotation.z;
             //Debug.Log("Rotationz = " + rotationz);
             transform.eulerAngles = Vector3.Slerp(myTransform.eulerAngles = new Vector3(0, 0, rotationz), defaultRotation, rotSpeed * Time.deltaTime);
         }
     }
 }
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 DanSuperGP · Feb 09, 2015 at 10:50 PM

Your problem is here...

rotSpeed * Time.deltaTime;

That's not how lerp / slerp works.

Lerp takes 3 elements. A starting position, an ending position, and T.

T is a number between 0 and 1

At T = 0 the Lerp will return the starting position, At T = 0.25 the Lerp will return the position 25% of the way along the line between the starting and ending position. At T = 0.5 the Lerp will return the position 50% of the way along the line between the starting and ending position. At T = 0.75 the Lerp will return the position 75% of the way along the line between the starting and ending position. At T = 1.0 the Lerp will return the ending position.

The reason it's popping is you're just setting T to rotSpeed * Time.deltaTime; Which is whatever rotSpeed is times something very small like 0.03... which is very close to zero, which looks like no rotation at all.

So what you want to do to get a smooth movement (or rotation) is to increase the value of T from zero to one smoothly over the amount of time that you want the movement to take.

I usually do it something like this

 IEnumerator lerpPosition( Vector3 StartPos, Vector3 EndPos, float LerpTime)
 {
    float StartTime = Time.time;
    float EndTime = StartTime + LerpTime;
 
    while(Time.time < EndTime)
    {
       float timeProgressed = (Time.time - StartTime) / LerpTime;  // this will be 0 at the beginning and 1 at the end.
       transform.position = Mathf.Lerp(StartPos, EndPos, timeProgressed);
 
      yield return new WaitForFixedUpdate();
    }
 
 }

Comment
Add comment · Show 7 · 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 SelfishGenome · Feb 10, 2015 at 07:36 AM 0
Share

Thanks that makes sense, I've done something like that in the past on key movement, but I think I've just confused myself trying to get it working with just the mouse. I also didn't fully understand how Lerp works I guess. I'll try that approach when I get back from work.

avatar image tanoshimi · Feb 10, 2015 at 10:22 AM 1
Share

It's actually very common to see Lerp used to change a transform in exactly this way (including, for example, in the official Unity tutorials). It's "incorrect" in the sense that you don't end up with a linear movement (which is what the "L" of Lerp stands for...), because you're changing the start position of the Lerp in each frame and keeping the same delta, ins$$anonymous$$d of keeping the same start and changing the delta. There's a good explanation of why this is wrong at http://www.blueraja.com/blog/404/how-to-use-unity-3ds-linear-interpolation-vector3-lerp-correctly.

However, while incorrect, it's not the cause of the "popping" described in this case - that's due to other problems with the code (although you should fix this too!)

avatar image DanSuperGP · Feb 10, 2015 at 05:42 PM 0
Share

Omg, no wonder I'm seeing this crazy way of using lerp popping up all over answers. I thought I was going crazy.

avatar image SelfishGenome · Feb 10, 2015 at 08:58 PM 0
Share

Ok DanSuperGP, I went with your approach as on paper so speak, it makes more sense. Tanoshimi, the way in the link you provided and the information was very helpful to get me understanding lerping/slerping correctly though. Thank you.

Now I have the problem that it will lerp perfectly when going left on the screen. However when traveling right, rather than going from a rotation of say 320 degrees up to 0. it goes the full 320 degree turn back down to zero, so an aerial role is carried out. I have corrected what Tanoshimi pointed out about the rotation.z error.

Also I realise a lot of the rotation at the top of the script is still incorrect, I am focusing on the bottom section for now to keep it simple, when that is fixed I think I will start from scratch.

             if (destinationDistance < 5f)
             {
                 StartCoroutine(lerpPos(transform.eulerAngles, transform.eulerAngles.normalized, rotSpeed));
     
             }
     
     
             
         }
     
         IEnumerator lerpPos(Vector3 startPos, Vector3 endPos, float lerpTime)
         {
             float startTime = Time.time;
             float endTime = startTime + lerpTime;
     
             while (Time.time < endTime)
             {
                 float timeProgressed = (Time.time - startTime) / lerpTime;
                 transform.eulerAngles = Vector3.Slerp(startPos, endPos, timeProgressed);
                 
                 yield return new WaitForFixedUpdate();
             }
     
         }
     
     }
 

I've added the code again (just the bits which have changed) for comparison.The only thing I can think is that transform.eulerAngles = Vector.Slerp... is not he correct approach???

avatar image tanoshimi · Feb 10, 2015 at 09:00 PM 2
Share

For angles that wrap around 360, you need LerpAngle...

Show more comments
avatar image
2

Answer by tanoshimi · Feb 09, 2015 at 10:47 PM

You've got some very confused code here, but the biggest problem is that you're treating rotationz as if it were the rotation around the z axis. It's not, it's the z component of a quaternion:

 Quaternion playerRotation = myTransform.rotation;
 float rotationz = playerRotation.z;

So you can't use it as the z component of a Vector3:

 transform.eulerAngles = Vector3.Slerp(myTransform.eulerAngles = new Vector3(0, 0, rotationz), defaultRotation, rotSpeed * Time.deltaTime);

(There's other problems with that line, but I think this is the problem at hand)

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 DanSuperGP · Feb 09, 2015 at 10:54 PM 0
Share

Yes. This is another problem.

Also, he's using lerp incorrectly.

avatar image SelfishGenome · Feb 10, 2015 at 07:29 AM 0
Share

Thanks for the quick reply, when I get back from work I will try to tidy the code a little.

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

3 People are following this question.

avatar image avatar image avatar image

Related Questions

Unit rotation fails consistently on all slerp rotations after the first? 0 Answers

Use Lerp to rotate object 2 Answers

HoloLens - Smooth Rotation doesn't work 0 Answers

Smoothing the characters rotation with Lerp 2 Answers

How can I use lerp to rotate an object multiple times? 2 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