Smoothing the roll with Mathf.Lerp or similar?

I’ve been posting the the course Q&A and trying different things, but my lack of intuitive math skills is really starting to let me down and frustrate me.

Based on some code in a similar thread I’m trying to get this to work:

    //Roll
    float roll;
    float targetRoll = xThrow * controlRollFactor;
    float currentRoll = transform.localEulerAngles.z;
    float rollDelta = Mathf.DeltaAngle(currentRoll,targetRoll);
    print(rollDelta);

    roll = Mathf.Lerp(currentRoll, rollDelta, .1f);
            
    //Rotate
    transform.localRotation = Quaternion.Euler(pitch, yaw, roll);

However it keeps flipping my plane a full 180.

Similar code I used previously was spinning the ship a full 360 so it is getting better… but I’d love some help.

It’s been a long time since I was writing this code / working on this section. When I look at your code, I don’t see offhand why it’s giving you trouble. Maybe if you compare how I handle pitch/roll/yaw you can discover something you didn’t notice before? Sorry I can’t be more helpful…

private void SetLocalAngles()
{
    if ((float.IsNaN(skewVertical) && float.IsNaN(skewHorizontal)) || !alive) return;

    // set a desired pitch and yaw based on screen position (and controlAxis throw if applicable):
    Vector3 pos = transform.localPosition;
    float pitch = -pos.y * skewVertical - (controlAxis.y * skewThrow);
    float yaw = pos.x * skewHorizontal + (controlAxis.x * skewThrow);

    // set a desired roll when strafing left or right vs. aileron rolling:
    float roll;
    if (Time.time > rollTime + basePlayerRollDelay && rollDirection != 0) roll = rollDirection * 370;
    else roll = controlAxis.x * -skewRoll;

    // Lerp between prior rotation and desired fixed rotation:
    pitch = Mathf.SmoothStep(priorRotation.x, pitch, delta * skewLerp);
    yaw = Mathf.SmoothStep(priorRotation.y, yaw, delta * skewLerp);
    roll = Mathf.SmoothStep(priorRotation.z, roll, delta * skewRollLerp);
    roll = MonitorRoll(roll);

    // apply rotation for this update:
    transform.localRotation = Quaternion.Euler(pitch, yaw, roll);

    // Store this updates' rotations for use next update. (X Y Z = Pitch Yaw Roll, respectively.)
    priorRotation.x = pitch;
    priorRotation.y = yaw;
    priorRotation.z = roll;
}

private float MonitorRoll(float roll)
{
    if (roll < -350)
    {
        roll += 360;
        rollDirection = 0;
        rollTime = Time.time;
    }
    if (roll > 350)
    {
        roll -= 360;
        rollDirection = 0;
        rollTime = Time.time;
    }
    return roll;

}

1 Like

hey thanks, I’m happy to get a response on this, I havent had much help on the course Q&A. I’m going to have a dig at it tonight so I will definitely take a look at your code, thank you.

Then i think I need to move on and not get hung up on it. Might have to ask a maths wiz I know outside of the course.

I’m going to add some videos here to illustrate what I’m doing.

This is how the game looks with the course code (I’ve added pitch control on the second joystick to help illustrate the ‘snapping’

     //Yaw
    float yaw = transform.localPosition.x * positionYawFactor;

    //Pitch
    axisFiveThrow = CrossPlatformInputManager.GetAxis("Pitch");
    float pitchDueToPosition = transform.localPosition.y * positionPitchFactor * Time.deltaTime;
    float pitchDueToControlThrow = axisFiveThrow * controlPitchFactor;
    float pitch = pitchDueToControlThrow + pitchDueToPosition;
    
    //Roll
    float roll = xThrow * controlRollFactor;
                    
    //Rotate
    transform.localRotation = Quaternion.Euler(pitch, yaw, roll);

If you move left/right the ship should roll from position, but ALSO have extra roll from the control throw. When you release the control that extra roll needs to smoothly return to the roll JUST from position.

Here is an example of it working when moving left, but flipping when moving right.

The code for this looks like:

    // To Do - Smooth the roll
    float targetRoll = xThrow * controlRollFactor;
    float currentRoll = transform.localEulerAngles.z;
    float rollDelta = Mathf.DeltaAngle(currentRoll,targetRoll);
    float roll = Mathf.Lerp(currentRoll, rollDelta, .1f);

the .1f in the lerp is an arbitrary number I reached through experimentation. I tried using time.deltatime but it doesnt work.

I have one more example to come

and here is where I started down the rabbit hole. It works beautifully moving left, but spins the plane 360 moving right.

 //Roll
 float currentRoll = transform.localEulerAngles.z;
 float roll = Mathf.Lerp(currentRoll, xThrow * controlRollFactor,.1f);

I was asked what I think the equation is doing each frame.

from my limited understanding it should be taking the current roll rotation and the amount of roll that is being applied by the stick and moving that number towards the other at the rate of .1f each frame.

It looks like it works. But when moving left current roll is a number between 0 and my controlRollFactor. When moving right it is from 0 to 360-controlRollFactor

If I try and determine if I’m moving left or right it sort of works, but because it could also be on the left or right due to position it bugs out and flips the plane anyway.

I’m not certain, but thinking this might be related to where 360 degrees becomes 0 degrees… In my code above you see that before I accept the roll value I have a:
float MonitorRoll(float val)
function which, if I recall, I needed for a similar reason.

Thanks, yes I saw that you had that check in place. I tried to just dump it in my code and see what happened but it didnt work ‘as is’. I’ve kept it in there to play with as i go on, but I’m concentrating on getting the rest of the game built now.

I appreciate your input! :slight_smile:

What’s up Gomisan, I don’t know if you were able to fix the 360 degree wraparound issue, but in case you or others haven’t, I just found a class called LerpAngle which is the same as Lerp, except it just interpolates correctly when the angle values wrap around 360 degrees.

So your code up above would simply read:

float currentRoll = transform.localEulerAngles.z;
float roll = Mathf.LerpAngle(currentRoll, xThrow * controlRollFactor,.1f);

There are still some issues with the controls I would personally like to work out, but we’re getting somewhere close to acceptable gameplay at least.

Happy developing!

This topic was automatically closed 24 hours after the last reply. New replies are no longer allowed.

Privacy & Terms