Leaning Banking

Is there a cheating way to lean the player with script when we drive in a curve?
can we just rotate the axis depends on speed and rotation around the y axis?

y rotation increase over time and we lean the rotation around the z axis?

I would organize my prefab thusly:

PivotingPointForLeaning
AllVisibleStuffHereOrBelow```

Then the script would compute a lean angle based on how much you're turning and how fast you're going and tilt over the PivotPointForLeaning by the appropriate amount.

// just guessing a formula that might be fun
float leanAngle = ForwardSpeed * TurningInputAngle * SomeRandomMagicalConstant;

if (leanAngle > MaxLeanAngle)
{
Debug.Log( “You have crashed and you simply don’t know it yet.”);
return;
}

PivotPointForLeaning.localTransform = Quaternion.Euler( 0, 0, leanAngle);

2 Likes

Thats interesting, i play a bit with it.
Thank you.

I took a quick whack at it myself over coffee… it works decently enough for the simple 2D case. See enclosed package.

7985124–1025685–BicycleTilting.unitypackage (64.4 KB)

1 Like

The code works really great.

but my problem is, that we have not really a steering input :

The values come from a stationary device , something like this:

so in the video you see the values the bike transfers.
So the question is.
Can we detect a curve and in what direction goes the curve?
The bike drives on a SWS spline.

when i dont clamp the Z axis i rotate wild around it
when i clamp it the rotation is more random.

can we arrange something with physics?

You should be able to some quick and dirty math that should give you some decent results. (my solution to most everything is quick and dirty math). :wink:
I haven’t looked at SWS in a long time, but there should/may be something that can help with that. If not, you can simple look head on the path (and possibly behind if you want to get more accurate). and then based on your current position and how far ahead determine a degree of tilt based on that. May take a few tries to get it to look right, but that is how I would go vs. a full physics solution.

1 Like

yes, physics is not really a solution for this.
i try further and write my progress back.

What other solution could there possibly be?! :slight_smile: I love quick and dirty math.

Andreas, if you are receiving just a series of positions or rotations along the spline, the quick and dirty math you need is going to be something like one of these things:

  • observe heading, compare it to previous frame (which you store), and extrapolate the change into a lean.

  • observe position change (eg, how much it moved) and compare to previous frame, then see how much that deviates laterally from the primary direction (eg, how much it goes sideways each frame).

Scaling up by magic numbers might get you a good proxy for a lean. Remember a little lean goes along way visually. We’re very sensitive visually to a tilt away from vertical.

ALSO: if you observe output from something like this, the signal may be noisy, which would make the leaning very jittery. In this case just implement a filter where you only take a fraction of the input signal each frame, to prevent noise from jittering you too much. Lerp makes a great poor man’s low pass filter for this.

https://discussions.unity.com/t/807121/2

https://discussions.unity.com/t/818601/4

1 Like

ok lets start to get the values:

 // raw input:
        float y = euler.y;
        // smooth it
        axis = Mathf.Lerp(axis, y, Snappiness * Time.deltaTime);
        Debug.Log("axis_Y" + axis);

makes sense to round to an INT? so we have not the comma floats?

Now we get some values for the Y axis:
140 , 140, 141, 142, …

we move always forward, thats good to know :slight_smile:
so if the value increase 140,141,142,143… n. we make a right curve, if value decrease we make a left curve?

so we can:
if value > prevValue{
lean 5 on the z axis
}
if value < prevValue{
lean-5 on the z axis
}
else{
lean = 0
}

thats my idea behind it?

I am now so far here:

 // raw input:
        float y = euler.y;
        float lastAxis = axis;
        // smooth it
        axis = Mathf.Lerp(axis, y, Snappiness * Time.deltaTime);
        axis = Mathf.RoundToInt(axis);
        Debug.Log("RoundedAxis_Y" + axis);
        if (lastAxis > axis)
        {
            euler.z += 15f;
        }
        if (lastAxis > axis)
        {
            euler.z -= 15f;
        }
        else
        {
            euler.z = 0f;
        }
lastAxis = axis

its not correct, but it should be a start to go further

Now we are steps further:

if (euler.y > 180) euler.y = euler.y - 360;

        transform.eulerAngles = euler;



        // raw input:
        float y = euler.y;
        float lastAxis = axis;
        // smooth it
        axis = y;// Mathf.Lerp(axis, y, Snappiness * Time.deltaTime);
        axis = Mathf.RoundToInt(axis);
        Debug.Log("RoundedAxis_Y" + axis);
        if (lastAxis > axis)
        {
            euler.z += 15f;
        }
        if (lastAxis > axis)
        {
            euler.z -= 15f;
        }
        if (axis == lastAxis)
        {
            euler.z += 0.01f;
        }
        lastAxis = axis;

i think now i need only dirty math to tell minus is not minus, or something like this.