# Low-Poly FPS Zombie Survival: Complete Implementation & Level Building Walkthrough This comprehensive guide expands upon the **LowPolyFPSGuide** specification, providing a complete end-to-end blueprint for building a commercial-quality, low-poly FPS zombie survival game in Unity using the Universal Render Pipeline (URP), Synty Studios assets, and Unity's modern package ecosystem. --- ## Table of Contents 1. [Architecture & System Flowchart](#1-architecture--system-flowchart) 2. [Project Configuration & Physics Matrix](#2-project-configuration--physics-matrix) 3. [Asset Ingestion & Rigging (Synty Studios)](#3-asset-ingestion--rigging-synty-studios) 4. [Player Character Implementation](#4-player-character-implementation) 5. [Weapon & Ballistics Systems (Hitscan & Projectiles)](#5-weapon--ballistics-systems-hitscan--projectiles) 6. [Pickups & Resource Economy (Ammo, Health, Weapons)](#6-pickups--resource-economy-ammo-health-weapons) 7. [Zombie AI & Dynamic Wave Spawners](#7-zombie-ai--dynamic-wave-spawners) 8. [Level Design, Navigation, & Environmental Mechanics](#8-level-design-navigation--environmental-mechanics) 9. [UI Canvas, HUD, & Post-Processing](#9-ui-canvas-hud--post-processing) 10. [Step-by-Step Level Construction Tutorial](#10-step-by-step-level-construction-tutorial) 11. [Verification Checklist & Debugging Guide](#11-verification-checklist--debugging-guide) --- ## 1. Architecture & System Flowchart The game is built upon a decoupled, event-driven architecture where player actions, weapons, pickups, and enemies communicate cleanly via dedicated managers. ``` +----------------------+ | UIController (HUD) | +----------^-----------+ | +---------------+---------------+ | | (Health changed, Ammo updated, | | Zombies left, Banners) +---------+--------+ +--------+--------+ | Player Controller| | AreaClearance | | & Health System | | Manager | +----+--------+----+ +----+-------+----+ | | | | (Move/Look)| | (Damaged/Healed) | | (All cleared) v v v v +-------+---+ +--+-----------+ +------+---+ +-+-----------+ |Character | |Health & Ammo | | Enemy | |Interactive | |Controller | |Pickups | | Spawner | |Doors & Exit | +-----------+ +--------------+ +----+-----+ +-------------+ | | (Spawns & tracks) v +------------------+ +----+-------------+ | WeaponController |<--------->| EnemyController | | (Hitscan/Rocket) | (Damage) | (Melee & Ranged) | +------------------+ +------------------+ ``` ### Script Inventory All scripts reside under `Assets/Scripts/`: * `PlayerController.cs`: First-person locomotion, pitch/yaw clamping, sprinting, jump physics. * `PlayerHealthController.cs`: Singleton managing hit points, damage mitigation, health events, and game over. * `Weapon.cs`: Multi-mode weapon supporting both raycast hitscan and physical explosive projectiles, ammo reserves, and reload logic. * `WeaponsController.cs`: Weapon switching, inventory slots, fire triggers, and HUD communication. * `Projectile.cs`: Physical ballistic / explosive projectile with collision sweeping, splash damage falloff, and impact effects. * `PickupItem.cs`: Base class for world pickups featuring procedural hover bobbing, 3D rotation, and respawn logic. * `AmmoPickup.cs`: Replenishes current weapon magazine or reserve ammo. * `HealthPickup.cs`: Restores player HP via `PlayerHealthController`. * `WeaponPickup.cs`: Unlocks and auto-equips new weapons found in the arena. * `EnemyController.cs`: NavMesh-driven state machine (Idle, Chase, Attack, Dead) supporting melee strikes or ranged projectile spitting. * `EnemySpawner.cs`: Configurable spawn waves with editor gizmos, managing living enemy quotas. * `AreaClearanceManager.cs`: Objective tracker unlocking arena gates and scene exits when all hostiles are eliminated. * `HazardZone.cs`: Environmental hazard dealing damage over time or instant death (slime, fire pits, kill planes). * `InteractiveDoor.cs`: Animated gate opening upon objective clearance or proximity. * `LevelExit.cs`: Transition volume loading subsequent scenes. * `UIController.cs`: Singleton updating HUD sliders, ammo readout, kill counters, dynamic banners, and game-over screens. --- ## 2. Project Configuration & Physics Matrix ### 2.1 Package Requirements Ensure the following packages are present in `Packages/manifest.json`: * **Universal RP** (`com.unity.render-pipelines.universal`) * **AI Navigation** (`com.unity.ai.navigation`) * **Input System** (`com.unity.inputsystem`) * **TextMeshPro / UGUI** (`com.unity.ugui`) ### 2.2 Layer Configuration Open **Edit > Project Settings > Tags and Layers** and set up User Layers: * Layer 3: `Player` * Layer 6: `Enemy` * Layer 7: `Ground` * Layer 8: `Interactable` * Layer 9: `Projectile` * Layer 10: `Hazard` ### 2.3 Physics Collision Matrix Navigate to **Edit > Project Settings > Physics**: 1. **Enemy vs Enemy**: **Uncheck** to allow zombies to swarm without getting snagged on each other's colliders. 2. **Projectile vs Player**: **Uncheck** so player projectiles never hit the shooter. 3. **Projectile vs Enemy**: **Check** to register direct weapon hits. 4. **Projectile vs Ground**: **Check** so missed shots hit walls, floors, and obstacles. --- ## 3. Asset Ingestion & Rigging (Synty Studios) ### 3.1 Model Import & Rigs 1. Select all character FBX models (e.g. Synty POLYGON Apocalypse, Zombies, or City). 2. In the **Rig** tab: * **Animation Type**: Set to `Humanoid`. * **Avatar Definition**: Set to `Create From This Model`. * Click **Apply**. 3. In the **Materials** tab: * Set material shader to `Universal Render Pipeline/Lit` or `Universal Render Pipeline/Simple Lit`. * Assign the bundled Synty texture palette atlas (e.g., `PolygonApocalypse_Texture_01_A.png`). ### 3.2 Socket Hierarchy To cleanly position weapons in the player's or character's hands: 1. Expand the character rig: `Root > Pelvis > Spine > Upper_Chest > R_Clavicle > R_UpperArm > R_Forearm > R_Hand` 2. Create an empty child GameObject named `Weapon_Socket_R`. 3. Set its local position and rotation to align with your weapon grip. --- ## 4. Player Character Implementation ### 4.1 Player GameObject Hierarchy Build the player GameObject as follows: ``` Player (Tags: "Player", Layer: "Player") |-- CharacterController (Height: 1.8, Radius: 0.35, Center: 0, 0.9, 0) |-- PlayerInput (Default map: "Player") |-- PlayerController.cs |-- PlayerHealthController.cs |-- WeaponsController.cs |-- CameraHolder (Local Position: 0, 1.6, 0) |-- Main Camera (Local Position: 0, 0, 0) |-- Weapon_Socket (Local Position: 0.25, -0.25, 0.5) |-- Gun_01_Rifle (Active) |-- Gun_02_RocketLauncher (Inactive) ``` ### 4.2 Configuring Inspector Fields * **PlayerController**: * `Walk Speed`: `5.0` * `Sprint Speed`: `8.5` * `Gravity`: `-19.62` * `Jump Height`: `1.2` * `Camera Holder`: Drag `CameraHolder` transform. * `Mouse Sensitivity`: `2.0` * `Up Down Look Limit`: `80.0` * **PlayerHealthController**: * `Max Health`: `100` * **WeaponsController**: * `Weapon Slots`: Size `2` (Assign equipped `Gun_01_Rifle` and `Gun_02_RocketLauncher`). * `Player Camera`: Drag `Main Camera`. * `Hit Mask`: Select `Default`, `Ground`, `Enemy`. --- ## 5. Weapon & Ballistics Systems (Hitscan & Projectiles) The included `Weapon.cs` supports two distinct ballistics paradigms out of the box: ### 5.1 Hitscan Weapon Setup (Assault Rifle / Pistol / Shotgun) For immediate bullet registration (instant raycast): 1. Attach `Weapon.cs` to the rifle model. 2. In the Inspector: * `Weapon Name`: `Assault Rifle` * `Damage`: `25` * `Fire Rate`: `0.12` * `Range`: `100` * `Max Ammo`: `30` * `Reload Time`: `1.5` * `Use Projectile`: **Unchecked (false)** * `Infinite Reserve`: `false` * `Current Reserve Ammo`: `90` * `Max Reserve Ammo`: `180` * `Muzzle Flash`: Assign muzzle ParticleSystem. * `Impact Effect Prefab`: Assign spark / dust impact prefab. * `Muzzle Point`: Child empty GameObject placed at barrel tip. ### 5.2 Physical Projectile Setup (Rocket Launcher / Grenade / Plasma) For weapons that launch physical geometry with travel time and splash damage: 1. Create a `Rocket.prefab`: * Add a 3D projectile model. * Add a `SphereCollider` (Is Trigger = `true`). * Attach `Projectile.cs`. * Configure `Projectile.cs`: * `Speed`: `40` * `Life Time`: `5` * `Damage`: `80` * `Is Explosive`: `true` * `Explosion Radius`: `4.5` * `Impact Effect Prefab`: Assign explosion VFX prefab with light flash. 2. Attach `Weapon.cs` to the launcher GameObject: * `Use Projectile`: **Checked (true)** * `Projectile Prefab`: Drag `Rocket.prefab`. * `Projectile Speed`: `40` * `Fire Rate`: `0.8` * `Max Ammo`: `4` --- ## 6. Pickups & Resource Economy (Ammo, Health, Weapons) All pickups inherit from `PickupItem.cs`, providing smooth continuous rotation and hover sine-wave bobbing. ### 6.1 Health Pickup * Create a 3D Medkit prefab. * Add a `BoxCollider` (Is Trigger = `true`). * Attach `HealthPickup.cs`: * `Heal Amount`: `35` * `Only Collect When Damaged`: `true` * `Pickup Message`: `"+35 Health Restored"` * `Respawns`: `true` (Respawn Time: `20`s) ### 6.2 Ammo Pickup * Create an Ammo Crate prefab. * Add a `BoxCollider` (Is Trigger = `true`). * Attach `AmmoPickup.cs`: * `Ammo Amount`: `30` * `Target Weapon Name`: Leave blank to feed active weapon, or enter `Assault Rifle`. * `Pickup Message`: `"+30 Ammo Acquired"` * `Respawns`: `true` (Respawn Time: `15`s) ### 6.3 Weapon Pickup * Place a weapon on a pedestal in the arena. * Add a `SphereCollider` (Is Trigger = `true`). * Attach `WeaponPickup.cs`: * `Weapon Slot Index`: `1` (Unlocks/swaps to secondary weapon). * `Pickup Message`: `"Rocket Launcher Acquired!"` * `Respawns`: `false` --- ## 7. Zombie AI & Dynamic Wave Spawners ### 7.1 Zombie Prefab Assembly 1. Drag a Synty Zombie FBX model into the scene. 2. Add components: * `CapsuleCollider`: Center `(0, 0.9, 0)`, Radius `0.3`, Height `1.8`. * `NavMeshAgent`: Speed `3.5`, Angular Speed `180`, Stopping Distance `1.5`, Height `1.8`, Radius `0.3`. * `Animator`: Assign your Zombie Animator Controller. * `EnemyController.cs`: * `Max Health`: `60` * `Attack Damage`: `15` * `Attack Range`: `1.8` * `Attack Cooldown`: `1.2` * `Detection Radius`: `18` * Tag: `Enemy`, Layer: `Enemy`. 3. Save as `Assets/Prefabs/Enemies/Zombie_Standard.prefab`. ### 7.2 Ranged Zombie Variant (Acid Spitter) 1. Duplicate `Zombie_Standard.prefab` to create `Zombie_Spitter.prefab`. 2. In `EnemyController.cs`: * `Is Ranged Enemy`: `true` * `Attack Range`: `12` * `Ranged Projectile Prefab`: Assign an acid blob projectile with `Projectile.cs` (configured with `Damage = 10`, `Speed = 20`). * `Projectile Spawn Point`: Transform at the zombie's head or mouth. ### 7.3 Dynamic Wave Spawning (`EnemySpawner.cs`) Instead of manually placing all zombies, place `EnemySpawner` objects around the map: 1. Create an empty GameObject `WaveSpawner_Courtyard`. 2. Attach `EnemySpawner.cs`. 3. Create several child transforms around the perimeter as spawn points and drag them into the `Spawn Points` array. 4. Set: * `Total Enemies To Spawn`: `15` * `Time Between Spawns`: `2.5` * `Max Simultaneous Enemies`: `6` * `Spawn On Start`: `true` 5. The spawner automatically registers living zombies with `AreaClearanceManager`. --- ## 8. Level Design, Navigation, & Environmental Mechanics ### 8.1 Arena Geometry & NavMesh Baking 1. **Modular Grid Layout**: Assemble walls, floors, pillars, and barricades using Synty modular assets. Ensure all floor seams are snapped (`V` key vertex snapping or grid snapping). 2. **Static Flagging**: Select all static environmental props and tick the **Static** checkbox in the top-right of the Inspector. 3. **Bake NavMesh Surface**: * Add a `NavMeshSurface` component (from `Unity.AI.Navigation`) to the root `Environment` GameObject. * Agent Type: `Humanoid`. * Click **Bake**. Verify the walkable areas are highlighted blue in the Scene view. ### 8.2 Environmental Hazards (`HazardZone.cs`) To create acid pools, toxic spills, or pitfall kill volumes: 1. Place a 3D Plane or Cube over the hazard area. 2. Add a `BoxCollider` (Is Trigger = `true`). 3. Attach `HazardZone.cs`: * `Instant Kill`: `false` (or `true` for bottomless death pits). * `Damage Per Second`: `25` * `Damage Enemies`: `true` (Zombies stepping into acid also take damage). ### 8.3 Clearance-Linked Gates (`InteractiveDoor.cs`) 1. Create a security blast door or gate blocking progression. 2. Attach `InteractiveDoor.cs`: * `Open Offset Position`: `(0, 3.5, 0)` (Slides upwards). * `Open On Area Cleared`: `true`. 3. When `AreaClearanceManager` clears the final enemy, the door smoothly slides open. ### 8.4 Objective & Exit Portal (`AreaClearanceManager.cs` & `LevelExit.cs`) 1. Create an empty GameObject `GameManager`. 2. Attach `AreaClearanceManager.cs`. 3. Create an exit portal GameObject (e.g. glowing doorway or teleporter). 4. Add a `BoxCollider` (Is Trigger = `true`). 5. Attach `LevelExit.cs` (Set `Next Scene Name` to `"Level 2"`). 6. Drag the exit portal GameObject to the `Level Exit` field on `AreaClearanceManager`. The exit stays disabled until all enemies are defeated. --- ## 9. UI Canvas, HUD, & Post-Processing ### 9.1 HUD Hierarchy Create a Canvas (**Render Mode: Screen Space - Overlay**, Canvas Scaler: **Scale With Screen Size**, 1920x1080): ``` HUD_Canvas |-- UIController.cs |-- HealthBar (Slider, anchored Bottom-Left) | |-- Background (Dark Red) | |-- Fill (Bright Green) |-- AmmoText (TextMeshProUGUI, anchored Bottom-Right: "30 / 90") |-- ZombieCountText (TextMeshProUGUI, anchored Top-Center: "Zombies Left: 12") |-- NotificationText (TextMeshProUGUI, anchored Center: "") |-- GameOverPanel (Panel, fullscreen dark overlay, inactive by default) |-- TitleText ("YOU DIED") |-- RestartButton (Calls UIController.RestartCurrentScene) ``` ### 9.2 URP Post-Processing Volume 1. Create a `Global Volume` GameObject. 2. Add a `Volume` component, set to `Global`, and assign `DefaultVolumeProfile`. 3. Add overrides: * **Vignette**: Intensity `0.35`, Smoothness `0.4`. * **Color Adjustments**: Post Exposure `0.2`, Contrast `20`, Saturation `-15` (bleak apocalyptic grading). * **Bloom**: Threshold `1.0`, Intensity `1.2`. * **Film Grain**: Type `Thin 1`, Intensity `0.3`. --- ## 10. Step-by-Step Level Construction Tutorial Here is the exact step-by-step sequence to construct a functional combat arena from scratch: 1. **New Scene**: Create a new scene (`File > New Scene > Basic URP`). Save as `Assets/Scenes/Level1.unity`. 2. **Build Floor & Boundaries**: * Create an empty root GameObject `Environment`. * Snap modular floor tiles to cover a 40x40 meter arena. * Add perimeter walls (height at least 4 meters) to prevent the player or enemies from falling out. * Add interior cover: barricades, containers, low walls, crates. * Select `Environment` and check **Static**. 3. **Bake NavMesh**: * Add `NavMeshSurface` to `Environment`. * Click **Bake**. Ensure navigation mesh flows smoothly around all obstacles. 4. **Deploy Player**: * Create the `Player` GameObject at `(0, 1, 0)`. * Attach `CharacterController`, `PlayerInput`, `PlayerController`, `PlayerHealthController`, `WeaponsController`. * Create `CameraHolder` at `(0, 1.6, 0)` with child `Main Camera`. * Attach `Gun_01_Rifle` to the camera or hand socket with `Weapon.cs`. * Connect all references in the Inspector. 5. **Place Pickups**: * Drop 2x `HealthPickup` and 3x `AmmoPickup` in strategic side corridors and behind barricades. 6. **Place Hazards**: * Create a green glowing acid pool in the arena center with `HazardZone.cs`. 7. **Deploy Enemy Spawners**: * Place 2x `EnemySpawner` GameObjects at opposite ends of the arena. * Add 3 spawn transform nodes to each. * Assign `Zombie_Standard.prefab` and set total spawns to 8 each. 8. **Set Up Objectives & Exit**: * Place `GameManager` with `AreaClearanceManager.cs`. * Place an exit portal zone with `LevelExit.cs` behind an `InteractiveDoor`. 9. **Configure HUD & Lighting**: * Add the `HUD_Canvas` with `UIController.cs`. * Add directional sunlight with soft shadows and a `Global Volume` with color grading. 10. **Test Play**: * Hit **Play**. Walk, sprint, fire weapons, shoot zombies, collect ammo and health, clear the wave, and proceed through the unlocked exit! --- ## 11. Verification Checklist & Debugging Guide | System | Expected Behavior | Troubleshooting | |---|---|---| | **Locomotion** | WASD moves player; Shift sprints; Space jumps smoothly; mouse looks around without flipping. | Verify `CameraHolder` is assigned in `PlayerController`. Ensure `CharacterController` is enabled. | | **Input System** | Firing responds to left mouse button; Reload responds to R; switching responds to Q/E or scroll. | `WeaponsController` supports both `Fire` and default `Attack` input action names. | | **Hitscan Weapons** | Bullets hit target immediately; spawn impact VFX at hit point; reduce zombie health. | Check `hitMask` in `WeaponsController` includes `Enemy` layer. Verify Zombie has a Collider. | | **Projectiles** | Rockets travel forward; explode on impact; apply splash damage to nearby enemies. | Ensure `Projectile.cs` has correct `Damageable Layers` and `Is Explosive` is ticked. | | **Ammo Reserves** | Firing decrements magazine; reloading transfers from reserves; empty ammo triggers click sound. | Check `Infinite Reserve` setting on `Weapon.cs`. | | **Pickups** | Walking over medkit or ammo crate consumes item, plays SFX, and displays on-screen toast. | Verify pickup collider has `Is Trigger` checked. Ensure player GameObject is tagged `"Player"`. | | **Zombie AI** | Zombies detect player within 18m, chase along NavMesh, swing melee attack within 1.8m. | Verify NavMesh was baked (`NavMeshSurface`). Ensure Zombie has `NavMeshAgent` enabled. | | **Wave Spawning** | Enemies spawn sequentially up to the max living quota; auto-register with clearance manager. | Verify spawn point transforms are placed above the floor on valid NavMesh ground. | | **Objective Tracker** | Defeating each zombie decrements the UI counter; eliminating all opens door and exit portal. | Ensure `AreaClearanceManager` is present in scene and referenced by `LevelExit`. | | **Level Transition** | Stepping into active exit portal triggers scene load. | Ensure destination scene is registered in **File > Build Settings**. |