Godot Version
v4.6.2.stable.mono.official [71f334935]
Question
I’m trying to align the player character to the ground, but its rotation jitters when in between two surfaces with different normals. How can I fix this?
This is the code I’m using:
public void GroundCheck()
{
float shortestDist = Mathf.Inf;
Vector2 shortestNormal = Vector2.Zero;
Vector2 avgNormal = Vector2.Zero;
foreach(RayCast2D ray in groundRays)
{
ray.ForceRaycastUpdate();
if (ray.IsColliding())
{
if (Utils.AngleFromTo(ray.GetCollisionNormal(), UpDirection, true) <= FloorMaxAngle)
{
avgNormal += ray.GetCollisionNormal();
if ((ray.GlobalPosition - ray.GetCollisionPoint()).Length() < shortestDist)
{
shortestDist = (ray.GlobalPosition - ray.GetCollisionPoint()).Length();
shortestNormal = ray.GetCollisionNormal();
}
}
}
}
avgNormal = avgNormal.Normalized();
if (avgNormal != Vector2.Zero)
{
Vector2 groundNormal = avgNormal;
if (onGround) velocity = Utils.CrossWithForward(groundNormal) * velocity.Length() * Mathf.Sign(velocity.Dot(RightDirection));
else velocity -= Utils.ProjectVector(velocity, groundNormal, true);
onGround = true;
UpDirection = groundNormal;
lastGroundNormal = groundNormal;
if (shortestDist > 10f) GlobalPosition -= UpDirection * (shortestDist - 10f);
}
else
{
UpDirection = -gravityDir;
onGround = false;
}
}
public void AlignToUp()
{
Vector2 upDir = UpDirection;
float rotation = GlobalRotation; //check if correct
float theta = Mathf.Wrap(Mathf.Atan2(upDir.X, -upDir.Y) - rotation, -Mathf.Pi, Mathf.Pi);
float rotationSpeed = (isJumping || currMoveState == null) ? 9999999 : currMovePhysics.rotationSpeed;
rotation += Mathf.Clamp(rotationSpeed * (float)GetPhysicsProcessDeltaTime(), 0, Mathf.Abs(theta)) * Mathf.Sign(theta);
GlobalRotation = rotation;
}
I also tried using this for the GroundCheck:
public void GroundCheck()
{
if (IsOnFloor() && Utils.AngleFromTo(GetFloorNormal(), UpDirection, true) <= FloorMaxAngle)
{
//GD.Print(Mathf.RadToDeg(GetFloorAngle()));
Vector2 groundNormal = GetFloorNormal();
if (onGround) velocity = Utils.CrossWithForward(groundNormal) * velocity.Length() * Mathf.Sign(velocity.Dot(RightDirection));
else velocity -= Utils.ProjectVector(velocity, groundNormal, true);
onGround = true;
UpDirection = groundNormal;
lastGroundNormal = groundNormal;
}
else
{
UpDirection = -gravityDir;
onGround = false;
}
}
But the jittering for this is worse.