# 3D Flight with pure local rotation without roll creep

I'm working on a flight race game with a specific constraint and cannot find a solution. Hereinbelow, an image of a test scene.

My ship has a cylinder (children) in front of it from which I get a TargetYaw and a TargetPitch. Each of them is clamp between [-1,1]. After, I update my yaw and pitch angle of my parent object using this values.

private void UpdateYaw()
{
_deltaYaw = Mathf.Lerp(_deltaYaw, _targetYaw, _yawAcceleration * Time.deltaTime);
_yawAngle += _deltaYaw * _yawSpeed * Time.deltaTime;
}

private void UpdatePitch()
{
_deltaPitch = _targetPitch;
_pitchAngle = Mathf.LerpAngle(_pitchAngle, -(_deltaPitch * _pitchMaxAngle), _pitchAcceleration * Time.deltaTime);
}


This is where my constraint happens. My flying object upward vector must be align with the normal vector of the road it is following. But, at the same time, I need to keep the same controls over it. Hereinbelow how I get the angle to make this happens.

// hover
float _targetRoll = 0;
float _rollAngle = 0;
public float _rollAcceleration = 2;
private int layermask = (1 << 8);
private Vector3 oldDown = Vector3.down;
private Quaternion toRotation = Quaternion.identity, targetRotation = Quaternion.identity;
void UpdateHoverRoll()
{
RaycastHit hit;

if (Physics.Raycast(transform.position, oldDown, out hit, Mathf.Infinity, layermask) == true)
{
toRotation = Quaternion.LookRotation(transform.forward, hit.normal);
oldDown = -transform.up;
LocalRotationTarget = toRotation.eulerAngles.z;
}
_rollAngle = Mathf.Lerp(_rollAngle, _targetRoll, Time.deltaTime * _rollAcceleration);
}


So, now that I got my 3 angles I need to find a rotation system which after I apply my roll, pitch and yaw do not change how I control my ship. If I roll to 90 degrees, I must still yaw around my local up vector and pitch around my local right vector (my control don't get inverse) for exemple. Here an example of what i tried:

private void UpdateRotation()
{
Quaternion q = Quaternion.AngleAxis(_turnAngle, Vector3.Normalize( Quaternion.Euler(0, 0, LocalRotation) * Vector3.up))
* Quaternion.AngleAxis(_pitchAngle, Vector3.Normalize(Quaternion.Euler(0,0,LocalRotation) * Vector3.right))
* Quaternion.AngleAxis(LocalRotation, Vector3.forward);
transform.rotation = Quaternion.Lerp(transform.rotation, q, 1);
}