Snake Game Collision Detection Problem
Issue Description
In my 2D snake game, I’m experiencing issues with collision detection between two snake characters. The snakes occasionally pass through each other instead of colliding and changing direction as intended.
Current Behavior
- Snakes sometimes overlap or intersect during gameplay
- Collision detection appears inconsistent, especially during fast movements
OnTriggerEnter2D
is triggered, but doesn’t always prevent intersection
Expected Behavior
- Snakes should never pass through each other
- Upon collision, snakes should change direction or bounce off each other
- Collision detection should be consistent and reliable, even at high speeds
Technical Details
- Using Unity 2D
- Snakes are composed of multiple segments (head + body parts)
- Each segment has a Collider2D (CircleCollider2D) and Rigidbody2D
- Movement is grid-based, controlled by joystick input
- Current collision detection uses
OnTriggerEnter2D
Attempted Solutions
- Implemented custom collision logic in
OnTriggerEnter2D
- Tried adjusting collider sizes and physics settings
- Experimented with different collision detection modes
snippet code for player :
public float gridSize = 1f;
public float moveInterval = 0.1f;
public Joystick joystick;
public GameObject bodyTmp;
public float collisionCooldown = 0.5f;
public float pushForce = 10f;
private Vector2 direction = Vector2.right;
private Vector2 nextPosition;
private float highLimit;
private float widthLimit;
private bool isCollided = false;
private Rigidbody2D rb;
private void Start()
{
highLimit = Camera.main.orthographicSize;
widthLimit = highLimit * Camera.main.aspect;
nextPosition = transform.position;
rb = GetComponent<Rigidbody2D>();
rb.collisionDetectionMode = CollisionDetectionMode2D.Continuous;
InvokeRepeating(nameof(Move), moveInterval, moveInterval);
}
private void Update()
{
if (!isCollided)
{
HandleInput();
}
}
private void HandleInput()
{
Vector2 inputDirection = new Vector2(joystick.Horizontal, joystick.Vertical).normalized;
if (inputDirection != Vector2.zero)
{
direction = inputDirection;
}
}
private void Move()
{
if (isCollided) return;
nextPosition += direction * gridSize;
rb.MovePosition(nextPosition);
RotateHead();
}
private void RotateHead()
{
float angle = Mathf.Atan2(direction.y, direction.x) * Mathf.Rad2Deg;
transform.rotation = Quaternion.Euler(new Vector3(0, 0, angle - 90));
}
public void ChangeDirection()
{
transform.Rotate(0, 0, 180);
direction *= -1f;
nextPosition += direction * 0.5f;
rb.MovePosition(nextPosition);
}
private void OnCollisionEnter2D(Collision2D collision)
{
if (collision.gameObject.CompareTag("HeadEnemy") || collision.gameObject.CompareTag("bodyEnemy") || collision.gameObject.CompareTag("bodyExtension"))
{
HandleCollision(collision);
}
}
private void HandleCollision(Collision2D collision)
{
if (isCollided) return;
Vector2 collisionNormal = collision.contacts[0].normal;
Vector2 reflectDirection = Vector2.Reflect(direction, collisionNormal).normalized;
direction = reflectDirection;
nextPosition = transform.position + (Vector3)(direction * gridSize);
rb.velocity = Vector2.zero;
rb.AddForce(reflectDirection * pushForce, ForceMode2D.Impulse);
isCollided = true;
StartCoroutine(CollisionCooldown());
}
private IEnumerator CollisionCooldown()
{
yield return new WaitForSeconds(collisionCooldown);
isCollided = false;
}
Any insights or solutions would be greatly appreciated. Thank you!