Some skate physics problem

Hello y’all

I’m making a small skating game, mostly because I’m interested in mechanics but I’m stuck with an orientation problem I can’t figure out.

To adapt the rotation of the skater with respect to its environment, I break the logic into several components:

  • A PhysicRotation : Returns the Quaternion to go from the skater’s transform.up to the normal of the point he’s at
Quaternion GetPhysicsRotation()
    {
        Vector3 target_vec = Vector3.up;
        Ray ray = new Ray(transform.position, Vector3.down);
        RaycastHit hit;

        if(Physics.Raycast(ray, out hit, 1.05f*height))
        {
            target_vec = hit.normal;
        }

        return Quaternion.FromToRotation(transform.up, target_vec);
    }
  • A velocity rotation: So that the character faces the direction he’s going. This rotation is contrained to a plane
Quaternion GetVelocityRot()
    {
        Vector3 vel = rb.velocity;
        if(vel.magnitude > 0.2f)
        {
            vel.y = 0;
            Vector3 dir = transform.forward;
            dir.y = 0;
            Quaternion vel_rot = Quaternion.FromToRotation(dir.normalized, vel.normalized);
            return vel_rot;
        }
        else
            return Quaternion.identity;
    }
  • And finally, I an InputRotation that rotates the force applied for moving
  • All of this is then tied in this function:
void SkaterMove(Vector2 inputs)
    {
   

        Quaternion PhysicsRotation = aerial ? Quaternion.identity : GetPhysicsRotation(); // Rotation according to ground normal
        Quaternion VelocityRotation = GetVelocityRot();
        Quaternion InputRotation = Quaternion.identity;
        Quaternion ComputedRotation = Quaternion.identity;


        if(inputs.magnitude > 0.1f)
        {
            Vector3 adapted_direction = CamToPlayer(inputs);
            Vector3 planar_direction = transform.forward;
            planar_direction.y = 0;
            InputRotation = Quaternion.FromToRotation(planar_direction, adapted_direction);

            if(!aerial)
            {
                Vector3 Direction = InputRotation*transform.forward*Speed;
                rb.AddForce(Direction);
            }
        }

        ComputedRotation = PhysicsRotation*VelocityRotation*transform.rotation;
        transform.rotation = Quaternion.Lerp(transform.rotation, ComputedRotation, RotatingSpeed*Time.deltaTime);



    }

The thing works rather well, but always stumbles on one specific case. Here’s a video I made the explain it better:

Basically, when in the quarter, if the character’s speed carries him in the air, he does a strange spin and and breaks its flow. I can’t figure out where in the code I’m allowing it to do this. I’ve tried various tests, but I can’t figure out where the problem is.

Could anyone point me in the good direction ?

Thanks !

Hey - at around 0:30 you demonstrate a case that’s working (slow speed, player is touching the ramp at all time) and around 0:39 there’s a case that’s not working (higher speed, player is airborne for a short time). Could it be the part

 Quaternion PhysicsRotation = aerial ? Quaternion.identity : GetPhysicsRotation(); // Rotation according to ground normal

that’s causing the PhysicsRotation to be an identity quaternion for a moment, and then return to rotation according to ground normal?

But if it’s the identity quaternion, shouldn’'t it just keep its current rotation ? That was actually what I was expecting.

You are right, the way you are concatenating the rotations that should work.
Look at exactly 0:10 in the video - the instant you get airborne, the charakters rotation returns to horizontal. At that point it doesn’t really feel weird, but I guess the same happens on the ramp, which then leads to unexpected behaviour.
That rotation is not in the code you have shown - all rotations in the code shown are limited by the Lerp you are using, so they can’t cause instant rotations as seen in the video.

Your comment led me to an idea. Because the rotation is never touched outside of this Lerp. So, I monitored the difference between my current rotation and the computed rotation and sometimes, the difference amounts to 100 degrees. So I’m gonna try to clamp it to a max threshold, see if it improves. I’ll let you know !

Thanks !

1 Like

Hi! Try increasing the length of the downward raycast. I paused the video at 0:38 and you can see an arc on the red downward rays. To me, that makes me think they’re not touching the ground, which would make your PhysicsRotation be do nothing

Thanks y’all for your ideas. I think I figured it out. The Lerp speed was actually very high. A feature needed to for the quarter, but dreadful when moving in the air. Hence, I just added a AerialRotationSpeed and I just select which speed to use based on aerial boolean.

I’m implementing input rotation in the air, I’ll let you guys know !

Thanks to all of you !

1 Like

Nice, good luck then with the rest of the project! Looks really good by the way

Hey ! Here’s an update ! ((:

Hey I am a beginner at video game design and i want to know the general way you made the movement for a competition ( because i am a dunce )