Preview

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

Codebase

Player Movement

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]

Player Shooting

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

Enemy Spawning

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());
        }
    }
}