Move up/down with angle interpolation

I have an object with a move vector and based on it’s move vector, move speed, and angle it moves. That code is pretty simple and works fine so hopefully no need to post it.

When I hit a key I set a target height, so if it’s at 0 to start and I hit up the target height is say 20. There are only 3 set heights -20, 0, and 20 so it doesn’t do anything different if you hit up or down multiple times.

I also have a target angle which is simply the yaw. So here is my code for angling the object just for yaw:

if (MoveVector.x != 0 || MoveVector.z != 0)
{
    //Get our target rotation
    Quaternion targetAngle = TP_Controller.Instance.TargetAngle;

    //Interpolate our angle
    transform.rotation = Quaternion.Slerp(transform.rotation, targetAngle, Time.deltaTime * TurnSpeed);
}

What I am trying to figure out is how to handle the pitch rotation so it slowly angles to some angle like 45 then back to 0 when it gets close to the target height. Sort of like an S curve.

I tried just setting an angle until it reaches the height, but with small angles it starts freaking out and when it goes up right before it gets to the height it is a little jerky. Here is the code I am using:

if (MoveVector.x != 0 || MoveVector.z != 0)
{
    //Get our target rotation
    Quaternion targetAngle = TP_Controller.Instance.TargetAngle;

    //now angle according to level
    if (Mathf.Abs(transform.position.y - TP_Controller.Instance.TargetHeightLevel) > 1)
    {
        float xRot = transform.position.y < TP_Controller.Instance.TargetHeightLevel ? -60.0f : 60.0f;
        targetAngle.eulerAngles = new Vector3(targetAngle.eulerAngles.x + xRot, targetAngle.eulerAngles.y, targetAngle.eulerAngles.z);
    }

    //Interpolate our angle
    transform.rotation = Quaternion.Slerp(transform.rotation, targetAngle, Time.deltaTime * TurnSpeed);
}

Figured I would just post and see if anyone knows of a better solution. If you need more info/code let me know.

PS: Sorry if this should really be posted on forums.unity rather than answers.unity; I am still a little confused about the difference and I only made an answers account. I know there is a description, but according to the posts in both areas there doesnt’t seem to be much of a difference.

Mathematically calculate your rotation based on speed:

float rotX = (verticalSpeed / maximumVerticalSpeed) * 45

IF the object is traveling downwards at maximum speed, this will return -45. It will return 45 for upwards travel. If it is moving up at half maximum vertical speed, it will return 22.

EDIT: Took me a bit, but I have some test code that seems to do what you want it to do.

using UnityEngine;
using System.Collections;

public class TiltingGameObject : MonoBehaviour
{
	Vector3 lastPos;
	public float targetH = 20;
	public float maxDist = 20;
	public float maxAng = 45;
	public float rotSpeed = 10;
	void Start()
	{
		lastPos = transform.position;
	}
	void Update()
	{
		
		transform.Translate(0, 0 , 1);
		Vector3 diff = transform.position - lastPos;
		if (Mathf.Abs(transform.position.y - targetH) > 0.1f)
		{
			float rotX = Mathf.Abs(Mathf.Abs(transform.position.y-targetH)/maxDist) * (transform.position.y > targetH ? -1 : 1) * -maxAng;
			
			if (rotX > maxAng) rotX = maxAng;
			if (rotX < -maxAng) rotX = -maxAng;
			transform.rotation = Quaternion.Lerp(transform.rotation, Quaternion.Euler(new Vector3(rotX, 0, 0)), Time.deltaTime * rotSpeed);
		}
		
		lastPos = transform.position;
	}
}