So I’m setting up a Dynamic Rigidbody2D movement system (so Rigidbody2Ds won’t push each other), and I am struggling to figure something out
In the attached screenshot my character is moving to the bottom left, and it is colliding with the wall, but I am trying to figure out how, once the collision is detected, I’d make it move to the left (i.e.: “slide” along the wall)
Here’s my code
private void FixedUpdate()
{
Vector2 moveValue = _playerInputClass.Player.Move.ReadValue<Vector2>();
if (CheckCollision(moveValue, .25f))
{
//For now if I'm colliding I'm simply ignoring the input because, again, I'm trying to figure out how to do it
moveValue = Vector2.zero;
}
_rigidbody.MovePosition(_rigidbody.position + moveValue * movementSpeed * Time.fixedDeltaTime);
if (_playerInputClass.Player.Rotate.phase != InputActionPhase.Waiting)
{
Vector2 rotateValue = _playerInputClass.Player.Rotate.ReadValue<Vector2>();
_rigidbody.rotation = Mathf.Atan2(rotateValue.y, rotateValue.x) * Mathf.Rad2Deg;
}
}
private bool CheckCollision(Vector2 direction, float distance)
{
Array.Clear(_collisions, 0, _collisions.Length);
collider.Cast(direction, _collisions, distance);
foreach (var v in _collisions)
{
if (v.transform && v.transform.CompareTag("Wall"))
{
return true;
}
}
return false;
}
I suppose you can bounce a ray off the object you’re against and use the normal from that ray and use either Vector3.forward or Vector3.backward - depending on if the player is to the left or right of the object (and I guess, above or below it) alongside Vector3.Cross() to make a perpendicular direction, which can be the direction to move the player in.
There’s also overloads for many physics queries so you can perform a query such as “cast” from a specific pose (position/rotation) such as this: Unity - Scripting API: Rigidbody2D.Cast
So yes, you can modify the movement vector you have with the following dot-product calculation to remove the component of movement in the direction you hit (collision normal):
Almost there, but now when the player collides with the wall it has that famous 2D jittery behaviour. I always thought that that was because of moving the transform instead of the rigidbody and the render step is fighting with the physics step. But it’s not my case since I’m using Rigidbody2D.MovePosition to move it (I’ve also tried changing the rigidbody speed, but it didn’t worked)… Is it what the if that starts in line 111 of KinematicTopDownController.cs handles?
If you ask to move a kinematic body, it’ll be moved to that position, even if its into overlap but a Kinematic body doesn’t have a collision response so any jittery motion is motion you’ve told it to do.