This game prototype is a 2D top-down arcade-style shooter, inspired by classic "laser defender" or "space shooter" games. The player controls a ship that can move within the screen bounds and fire projectiles at waves of enemies. Features include player/enemy health, score tracking, particle hit effects, camera shake on damage, audio feedback for shooting and taking damage, and a UI displaying health and score. The game supports multiple input schemes (keyboard, mouse, gamepad, touch, joystick) via Unity's Input System, and includes a simple game over and main menu flow.
The core game mechanics revolve around dodging enemy projectiles, shooting enemies, and surviving as long as possible to achieve a high score. Enemies spawn in configurable waves and follow predefined paths, with each destroyed enemy increasing the player's score. The player loses when their health reaches zero, triggering a game over screen that displays the final score. The design uses ScriptableObjects
for wave configuration, modular MonoBehaviour
scripts for player/enemy logic, and Unity's UI system for feedback.
Technically, the project demonstrates foundational Unity C# skills: MonoBehaviour
scripting, coroutines for continuous actions (like firing), singleton patterns for persistent managers (audio, score), ScriptableObjects
for data-driven design, and event-driven input handling. By building this prototype, a developer gains experience in structuring a Unity project, managing game state, implementing responsive controls, and integrating visual/audio feedback—essential skills for any aspiring game
void Update()
{
Vector2 delta = new Vector2(Input.GetAxis("Horizontal"), Input.GetAxis("Vertical")) * moveSpeed * Time.deltaTime;
Vector2 newPos = new Vector2(
Mathf.Clamp(transform.position.x + delta.x, xMin, xMax),
Mathf.Clamp(transform.position.y + delta.y, yMin, yMax)
);
transform.position = newPos;
}
flowchart TD
A[Player Input] --> B[Calculate Movement Delta]
B --> C[Clamp Position to Screen Bounds]
C --> D[Update Player Position]
Description:
Enables the player to fire projectiles at enemies by pressing a shoot button, with a configurable fire rate.
IEnumerator FireContinuously()
{
while (isFiring)
{
Instantiate(laserPrefab, transform.position, Quaternion.identity);
yield return new WaitForSeconds(fireRate);
}
}
flowchart TD
A[Fire Button Pressed] --> B[Start Coroutine]
B --> C[Instantiate Laser Projectile]
C --> D[Wait for Fire Rate]
D --> C
Description:
Spawns waves of enemies at set intervals and positions, using ScriptableObjects
for configuration.
IEnumerator SpawnAllWaves()
{
foreach (WaveConfig wave in waveConfigs)
{
for (int i = 0; i < wave.GetEnemyCount(); i++)
{
Instantiate(wave.GetEnemyPrefab(), wave.GetWaypoints()[0].position, Quaternion.identity);
yield return new WaitForSeconds(wave.GetTimeBetweenSpawns());
}
}
}