Overview
Circle-circle collision detection is an algorithm that determines whether two circles overlap. It is frequently used in games to detect collisions between players and enemies, bullets and enemies, etc.
Collision Detection Code in ArrowController.cs
// Store arrow's current position as 2D vector
Vector2 p1 = transform.position; // Arrow
// Store player's current position as 2D vector
Vector2 p2 = player.transform.position; // Player
// Calculate direction vector from arrow to player
Vector2 direction = p1 - p2;
// Calculate distance between two objects (vector magnitude)
float d = direction.magnitude;
// Arrow collision radius
float r1 = 0.5f; // Arrow radius
// Player collision radius
float r2 = 1.0f; // Player radius
// Circle-circle collision detection
if (d < r1 + r2)
{
// Handle collision
}
Variable Explanation
p1 (Arrow Position)
Vector2 p1 = transform.position; // Arrow
- Meaning: Arrow's current position coordinates
- Type:
Vector2(x, y coordinates) - Example: If arrow is at (3, 5),
p1 = (3, 5)
p2 (Player Position)
Vector2 p2 = player.transform.position; // Player
- Meaning: Player's current position coordinates
- Type:
Vector2(x, y coordinates) - Example: If player is at (1, 2),
p2 = (1, 2)
direction (Direction Vector)
Vector2 direction = p1 - p2;
- Meaning: Direction vector from arrow to player
- Calculation:
p1 - p2= arrow position - player position - Example:
- p1 = (3, 5), p2 = (1, 2)
- direction = (3-1, 5-2) = (2, 3)
d (Distance)
float d = direction.magnitude;
- Meaning: Distance between two points (p1, p2)
- Calculation: Magnitude of direction vector
- Uses Pythagorean Theorem:
d = √(dx² + dy²)
r1 (Arrow Collision Radius)
float r1 = 0.5f; // Arrow radius
- Meaning: Arrow's collision area radius
- Value: 0.5 units
- Purpose: Collision range considering arrow size
r2 (Player Collision Radius)
float r2 = 1.0f; // Player radius
- Meaning: Player's collision area radius
- Value: 1.0 units
- Purpose: Collision range considering player size
Pythagorean Theorem and Distance Calculation
What is the Pythagorean Theorem?
In a right triangle, the square of the hypotenuse equals the sum of squares of the other two sides.
a² + b² = c²
Where:
- a, b: Two sides forming the right angle
- c: Hypotenuse
Distance Calculation in 2D Space
The Pythagorean theorem is used to calculate the distance between two points.
Distance = √((x2 - x1)² + (y2 - y1)²)
Visual Explanation
p1 (x1, y1)
|
| dy = y1 - y2
|
+-------- p2 (x2, y2)
dx = x1 - x2
- dx: Distance in x direction = x1 - x2
- dy: Distance in y direction = y1 - y2
- Distance d: Hypotenuse = √(dx² + dy²)
Implementation in Unity
Vector2 direction = p1 - p2;
// direction = (dx, dy) = (x1 - x2, y1 - y2)
float d = direction.magnitude;
// d = √(dx² + dy²)
Step-by-Step Calculation
// 1. Calculate direction vector
Vector2 direction = p1 - p2;
// Example: p1 = (3, 5), p2 = (1, 2)
// direction = (3-1, 5-2) = (2, 3)
// 2. Calculate distance (magnitude uses Pythagorean theorem internally)
float d = direction.magnitude;
// d = √(2² + 3²) = √(4 + 9) = √13 ≈ 3.606
Manual Calculation Example
// p1 = (3, 5), p2 = (1, 2)
float dx = 3 - 1; // dx = 2
float dy = 5 - 2; // dy = 3
// Calculate distance using Pythagorean theorem
float d = Mathf.Sqrt(dx * dx + dy * dy);
// d = √(2² + 3²) = √(4 + 9) = √13 ≈ 3.606
Circle-Circle Collision Detection
Collision Condition
For two circles to collide, the distance between their centers must be less than or equal to the sum of their radii.
Collision condition: d ≤ r1 + r2
Visual Explanation
No Collision
r1 r2
○ ○
| |
| d |
|-----------|
d > r1 + r2 → No collision
Collision
r1 r2
○ ○
| |
|d|
d < r1 + r2 → Collision!
Touching
r1 r2
○○
||
|d|
d = r1 + r2 → Touching (treated as collision)
Code Implementation
// Calculate distance
float d = direction.magnitude;
// Collision detection
if (d < r1 + r2)
{
// Collision occurred!
// Handle HP decrease, arrow deletion, etc.
}
Practical Examples
Example 1: No Collision
// Arrow position: (0, 5)
Vector2 p1 = new Vector2(0, 5);
// Player position: (5, 2)
Vector2 p2 = new Vector2(5, 2);
// Direction vector
Vector2 direction = p1 - p2; // (-5, 3)
// Distance
float d = direction.magnitude; // √(25 + 9) = √34 ≈ 5.83
// Radii
float r1 = 0.5f; // Arrow
float r2 = 1.0f; // Player
// Collision check
if (d < r1 + r2) // 5.83 < 1.5? → false
{
// No collision
}
Example 2: Collision
// Arrow position: (2, 3)
Vector2 p1 = new Vector2(2, 3);
// Player position: (1, 2)
Vector2 p2 = new Vector2(1, 2);
// Direction vector
Vector2 direction = p1 - p2; // (1, 1)
// Distance
float d = direction.magnitude; // √(1 + 1) = √2 ≈ 1.414
// Radii
float r1 = 0.5f; // Arrow
float r2 = 1.0f; // Player
// Collision check
if (d < r1 + r2) // 1.414 < 1.5? → true
{
// Collision occurred!
Debug.Log("Hit by arrow!");
}
Performance Optimization
Using Squared Distance
Instead of calculating the actual distance, using the squared distance eliminates the Mathf.Sqrt() operation, improving performance.
// ❌ Slow method: Calculate actual distance
float d = direction.magnitude; // Calculate √(dx² + dy²)
if (d < r1 + r2) { }
// ✅ Fast method: Use squared distance
float dSquared = direction.sqrMagnitude; // dx² + dy² (no square root)
float radiusSum = r1 + r2;
if (dSquared < radiusSum * radiusSum) { }
Optimized Code
// Calculate direction vector
Vector2 direction = p1 - p2;
// Calculate squared distance (without square root)
float dSquared = direction.sqrMagnitude;
// Squared sum of radii
float radiusSum = r1 + r2;
float radiusSumSquared = radiusSum * radiusSum;
// Collision check (compare squares)
if (dSquared < radiusSumSquared)
{
// Handle collision
}
Adjusting Radius Values
Meaning of Radius Values
It's good to set radius values slightly larger than the actual object size.
// If arrow's actual size is 0.3
float r1 = 0.5f; // Slightly larger value
// If player's actual size is 0.8
float r2 = 1.0f; // Slightly larger value
Testing Radius Values
// Make adjustable in Inspector
public float arrowRadius = 0.5f;
public float playerRadius = 1.0f;
void Update()
{
float d = direction.magnitude;
if (d < arrowRadius + playerRadius)
{
// Handle collision
}
}
Summary
Variable Summary
| Variable | Meaning | Calculation Method |
|---|---|---|
| p1 | Arrow position | transform.position |
| p2 | Player position | player.transform.position |
| direction | Direction vector | p1 - p2 = (dx, dy) |
| d | Distance between two points | √(dx² + dy²) (Pythagorean theorem) |
| r1 | Arrow collision radius | 0.5f |
| r2 | Player collision radius | 1.0f |
Collision Detection Formula
Collision condition: d < r1 + r2
Where:
d = √((x1 - x2)² + (y1 - y2)²) (Pythagorean theorem)
Key Concepts
- Pythagorean Theorem: Used to calculate distance between two points
- magnitude: Vector magnitude (distance)
- Circle-circle collision: Distance < sum of radii
- Performance optimization: Use squared distance (sqrMagnitude)
Practice Problems
-
Calculate the distance when the arrow is at (3, 5) and the player is at (1, 2).
-
Determine if a collision occurs when r1 = 0.5, r2 = 1.0, and distance = 1.2.
-
Change the code to use squared distance for performance optimization.
-
Change radius values to public variables so they can be adjusted in the Inspector.
-
Add code to output distance and radius values using Debug.Log when a collision occurs.