I have a floor made of 1m tiles at every square on Unity’s grid, each with its own box collider.
I apply horizontal force to my player rigidbody, and it often stops at random floor sections. I believe it is colliding with the microscopic differences in heights of the tiles, even though they are all set to a whole number. Why is this happening?
Edit: Here’s PlayerController.cs, seems pretty standard
private void FixedUpdate() {
// Move character
rb.AddForce(new Vector2( horizontalInput * moveAcceleration , 0f ));
// Clamp maximum velocity
rb.velocity = Vector2.ClampMagnitude(rb.velocity, maxMoveSpeed);
// Apply linear drag if input is not active
rb.drag = Mathf.Abs(horizontalInput) < 0.2f ? linearDrag : 0;
}
I’m assuming the Player RigidBody in question uses a Box Collider, which is why the corners get stuck. I’m also sure there is probably some solution in the Project Settings under Physics that maybe helps dampen this issue a little, but the generally accepted solution for a player is to use a Capsule Collider:
⠀
⠀
The reason these are used is that they have no sharp corners, meaning they can go up steps and slopes with no issues, as well as avoiding the issue you’re having, since there’s nothing to get caught on the edges.
⠀
However, that may not always work, like if you have an actual box, a Box collider just makes sense. From researching, it seems there’s not really an agreed solution. From this thread, some suggest using a series of rounded colliders on the edges, some suggest having a tile collider merging script, some say have a script on the box that uses Physics.IgnoreCollision etc. so I guess it’s just something that computers aren’t really good at and causes issues that you need to workaround.
public class RemovePlayerBumpiness : MonoBehaviour
{
// Stop the bumpiness that comes from moving along the ground
private Rigidbody2D rb;
private void Start() {
rb = GetComponent<Rigidbody2D>();
}
private void FixedUpdate() {
// If player isn't moving up or down, keep y position constant.
if (Mathf.Abs(rb.velocity.y) < 0.05f) {
transform.position = new Vector2(transform.position.x, Mathf.RoundToInt(transform.position.y));
}
}
}
It’s not a perfect solution but it seems to be working just fine so I’ll roll with it for now. I also changed Default Contact Offset to 0.0001 as suggested by @AaronBacon .