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);
        }
    }
}

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)

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();
   }

}