Game Overview
The arrow dodge game is a survival game where you avoid arrows falling from above. The player moves left and right to dodge arrows, and loses HP when hit by an arrow. The game ends when HP reaches 0.
Game Features
- Player Movement: Move player left and right with arrow keys
- Arrow Spawning: Spawn arrows from the top of the screen at regular intervals
- Arrow Falling: Spawned arrows fall downward
- Collision Detection: Detect collisions between player and arrows
- HP System: Decrease HP when hit by an arrow
- Game Over: Game ends when HP reaches 0
Project Structure
02.Scripts/
├── PlayerController.cs # Player movement control
├── GameManager.cs # Game state and HP management
├── ArrowGenerator.cs # Arrow spawning
└── ArrowController.cs # Arrow movement and collision detection
1. Player Controller (PlayerController.cs)
Features
- Receive left/right arrow key input
- Move player left and right
Implementation Code
using UnityEngine;
public class PlayerController : MonoBehaviour
{
// Player movement speed
public float moveSpeed = 0.2f;
void Update()
{
// Left arrow key input
if (Input.GetKey(KeyCode.LeftArrow))
{
// Move left
transform.Translate(-moveSpeed, 0, 0);
}
// Right arrow key input
if (Input.GetKey(KeyCode.RightArrow))
{
// Move right
transform.Translate(moveSpeed, 0, 0);
}
}
}
Key Concepts
- Input.GetKey(): Returns true continuously while key is pressed
- transform.Translate(): Moves relative to current position
- moveSpeed: Adjusts movement speed (adjustable in Inspector)
Unity Setup
- Create player GameObject
- Add PlayerController script
- Set player image with Sprite Renderer
- Adjust moveSpeed value (default: 0.2)
2. Game Manager (GameManager.cs)
Features
- Manage HP gauge
- Provide HP decrease method
Implementation Code
using UnityEngine;
using UnityEngine.UI;
public class GameManager : MonoBehaviour
{
// UI Image component to display HP gauge
public Image hpGauge;
// Method to decrease HP
public void DecreaseHp()
{
// Decrease HP gauge fill amount by 0.2
hpGauge.fillAmount -= 0.2f;
}
}
Key Concepts
- Image.fillAmount: Value between 0.0 (empty) and 1.0 (full)
- public method: Can be called from other scripts
Unity Setup
- Create GameManager GameObject
- Add GameManager script
- Create UI Canvas
- Add Image component (for HP gauge)
- Set Image Type to "Filled"
- Assign Image to GameManager's hpGauge
3. Arrow Generator (ArrowGenerator.cs)
Features
- Spawn arrows at regular intervals
- Spawn arrows at random X positions
Implementation Code
using UnityEngine;
public class ArrowGenerator : MonoBehaviour
{
// Arrow prefab object
public GameObject arrowPrefab;
// Arrow spawn interval (in seconds)
float spawnTime = 0.3f;
// Variable to accumulate elapsed time
float delta = 0f;
void Update()
{
// Accumulate time between previous and current frame
delta += Time.deltaTime;
// Check if accumulated time exceeds spawn interval
if (delta > spawnTime)
{
// Reset timer
delta = 0f;
// Clone prefab to create new arrow object
GameObject ar = Instantiate(arrowPrefab);
// Randomly determine X coordinate for arrow spawn
float px = Random.Range(-8.4f, 8.4f);
// Set spawned arrow's position
ar.transform.position = new Vector3(px, 6f, 0);
}
}
}
Key Concepts
- Time.deltaTime: Provides constant time interval regardless of framerate
- Instantiate(): Clones prefab to create new object
- Random.Range(): Generates random value
Unity Setup
- Create ArrowGenerator GameObject
- Add ArrowGenerator script
- Create arrow prefab (Arrow GameObject)
- Assign arrow prefab to ArrowGenerator's arrowPrefab
- Adjust spawnTime value (default: 0.3 seconds)
4. Arrow Controller (ArrowController.cs)
Features
- Move arrow downward
- Delete when off-screen
- Detect collision with player
- Decrease HP and delete arrow on collision
Implementation Code
using UnityEngine;
public class ArrowController : MonoBehaviour
{
// Arrow movement speed
public float arrowSpeed = 0.1f;
// Reference to player object
GameObject player;
void Start()
{
// Find and store reference to GameObject named "player" in scene
player = GameObject.Find("player");
}
void Update()
{
// Move arrow downward
transform.Translate(0, -arrowSpeed, 0);
// Check if arrow went too far below screen
if (transform.position.y < -6f)
{
// Remove arrow object from memory
Destroy(gameObject);
}
// Distance calculation for collision detection (circle-circle collision algorithm)
// 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: collision if distance between centers < sum of radii
if (d < r1 + r2)
{
// Find GameObject named "GameManager" in scene and get reference
GameObject gm = GameObject.Find("GameManager");
// Get GameManager component and call DecreaseHp() method
gm.GetComponent<GameManager>().DecreaseHp();
// Delete arrow object since collision detected
Destroy(gameObject);
}
}
}
Key Concepts
- GameObject.Find(): Find GameObject by name
- GetComponent(): Get component
- Vector2.magnitude: Vector magnitude (distance)
- Circle-circle collision: Distance between centers < sum of radii
Unity Setup
- Add ArrowController script to arrow prefab
- Adjust arrowSpeed value (default: 0.1)
- Set player GameObject name to "player"
- Set GameManager GameObject name to "GameManager"
Step-by-Step Implementation Guide
Step 1: Scene Setup
- Create New Scene: File > New Scene
- Camera Setup: Use Orthographic camera (2D game)
- Background Setup: Set background image or color
Step 2: Player Setup
-
Create Player GameObject
- GameObject > 2D Object > Sprite
- Rename to "player"
- Set player image with Sprite Renderer
-
Add PlayerController Script
- Create PlayerController.cs script
- Add to player GameObject
- Adjust moveSpeed value
Step 3: Game Manager Setup
-
Create GameManager GameObject
- Create empty GameObject
- Rename to "GameManager"
- Add GameManager.cs script
-
HP Gauge UI Setup
- Create Canvas (GameObject > UI > Canvas)
- Create Image (GameObject > UI > Image)
- Set Image Type to "Filled"
- Fill Method: Horizontal
- Fill Origin: Left
- Assign Image to GameManager's hpGauge
Step 4: Arrow Setup
-
Create Arrow Prefab
- GameObject > 2D Object > Sprite
- Rename to "Arrow"
- Set arrow image with Sprite Renderer
- Add ArrowController.cs script
- Drag to Prefabs folder to create prefab
-
ArrowGenerator Setup
- Create empty GameObject
- Rename to "ArrowGenerator"
- Add ArrowGenerator.cs script
- Assign arrow prefab to arrowPrefab
Step 5: Test and Adjust
- Run Game: Click Play button
- Adjust Speeds:
- Player movement speed (moveSpeed)
- Arrow fall speed (arrowSpeed)
- Arrow spawn interval (spawnTime)
- Adjust Collision Range:
- Arrow radius (r1)
- Player radius (r2)
Detailed Game Mechanics
1. Time-Based Arrow Spawning
delta += Time.deltaTime; // Accumulate time
if (delta > spawnTime) // When certain time elapsed
{
delta = 0f; // Reset timer
// Spawn arrow
}
- Time.deltaTime: Constant time regardless of framerate
- delta accumulation: Track elapsed time
- spawnTime: Adjust spawn interval
2. Circle-Circle Collision Detection Algorithm
Vector2 direction = p1 - p2; // Direction vector
float d = direction.magnitude; // Distance
if (d < r1 + r2) // Collision check
{
// Handle collision
}
- Distance between two points: Calculated using vector magnitude
- Collision check: Distance < sum of radii
- Radius adjustment: Set according to object size
3. HP System
hpGauge.fillAmount -= 0.2f; // Decrease HP by 20%
- fillAmount: Value between 0.0 and 1.0
- 0.2 decrease: Decrease by 20% each time
- Game over after 5 hits: Game over when fillAmount reaches 0
Game Improvement Ideas
1. Game Over Handling
public void DecreaseHp()
{
hpGauge.fillAmount -= 0.2f;
// Game over when HP reaches 0 or below
if (hpGauge.fillAmount <= 0f)
{
GameOver();
}
}
void GameOver()
{
Debug.Log("Game Over!");
Time.timeScale = 0f; // Pause game
}
2. Score System
public int score = 0;
public Text scoreText;
void Update()
{
// Score increases over time
score += (int)(Time.deltaTime * 10);
scoreText.text = "Score: " + score;
}
3. Difficulty Increase
float spawnTime = 0.3f;
float minSpawnTime = 0.1f;
void Update()
{
// Decrease spawn interval over time
spawnTime = Mathf.Max(minSpawnTime, 0.3f - Time.time * 0.01f);
}
4. Sound Effects
public AudioSource hitSound;
public AudioSource missSound;
void OnHit()
{
hitSound.Play();
}
void OnMiss()
{
missSound.Play();
}
Troubleshooting
Problem 1: Arrows Not Spawning
Cause: arrowPrefab not assigned Solution: Assign arrow prefab to ArrowGenerator's arrowPrefab
Problem 2: Collision Not Detected
Cause:
- Player or GameManager name incorrect
- Collision radius too small
Solution:
- Check GameObject names ("player", "GameManager")
- Increase r1, r2 values
Problem 3: HP Gauge Not Updating
Cause: hpGauge not assigned Solution: Assign Image component to GameManager's hpGauge
Problem 4: Arrows Too Fast or Slow
Cause: arrowSpeed value inappropriate Solution: Adjust ArrowController's arrowSpeed value
Summary
Core Script Roles
| Script | Role | Main Features |
|---|---|---|
| PlayerController | Player control | Left/right movement |
| GameManager | Game state management | HP management |
| ArrowGenerator | Arrow spawning | Timed spawning |
| ArrowController | Arrow control | Movement, collision detection |
Key Unity Features
- Input.GetKey(): Key input detection
- transform.Translate(): Object movement
- Instantiate(): Object creation
- Destroy(): Object deletion
- Time.deltaTime: Frame-independent time
- Vector2.magnitude: Distance calculation
- GameObject.Find(): Find object
- GetComponent(): Get component
Next Steps
Based on this game, you can add the following features:
- Game over screen
- Restart functionality
- Score system
- Difficulty increase
- Power-up items
- Sound effects
- Particle effects
Practice Problems
-
Add game over functionality so the game ends when HP reaches 0.
-
Add a score system that increases based on survival time.
-
Add a difficulty increase system so arrow spawn speed increases over time.
-
Add a screen flash effect when hit by an arrow.
-
Create a bonus system that adds points when the player dodges an arrow.