← All games
Team project

Project Galaxy (Orbit Unknown)

A 3D sci-fi FPS built by a 5-person Scrum team through Alpha, Beta, and QA sprints - enemy AI, inventory, objectives, and a full save system in four weeks.

timeline
Dec 2024 - Jan 2025
team
5-person team, Scrum (Alpha/Beta/QA)
my role
Enemy AI, boss, inventory, save system, objectives
contribution
#1 committer - 141 of 400 commits
Unity 2022.3C#NavMeshScriptableObjectsJSON persistenceCinemachineScrum

overview

Project Galaxy (working title Orbit Unknown) came out of Full Sail's Project & Portfolio II and III: the same five developers carried an FPS from first prototype (Dec 2024) into this build, at roughly 400 commits in four weeks. Every script carries an author header, and they match the git history - the systems below are mine, verifiable in the public repo.

what I built

  • Enemy AI class hierarchy. An abstract EnemyBase (NavMeshAgent movement, a template-method Behavior(), shared aim/shoot/reload handling, and damage that marks the enemy destroyed in save data) with three subclasses I wrote: a ranged enemy that roams and chases, a stun enemy running a Roaming/Chasing/Fleeing state machine that steals an item from your inventory and runs, and a barrier enemy - plus a targeting system using physics overlap queries with layer masks.
  • Boss fight with an ability-component pattern. The boss composes abilities behind an IBossAbility interface (charged laser, ground attack) executed per encounter, alternating keep-distance movement with charge attacks. The encounter system was scaffolded for three phases; the first shipped in the playable build.
  • ScriptableObject inventory. An abstract ItemBase ScriptableObject (weapons, ammo, collectibles, mission items, health) behind a singleton InventoryManager with slot-stacking math, inventory-changed events for the UI, and serializable inventory data for the save file.
  • JSON save/load with GUID persistence. A static save system writing JSON save slots to persistent storage, defensively returning a fresh save on missing, empty, or corrupt files. Every persistent object carries a UniqueID (editor-generated GUID), so killed enemies and picked-up items self-destroy on load - scene state survives both scene changes and app restarts.
  • Checkpoints, objectives, win/lose. A checkpoint manager that writes into the save file (overwrite or single-use modes), a respawn path in the player controller, and an objective manager with nine objective triggers hooked to UI and persisted completion state.
  • Weapon system (majority owner). A teammate created the weapon component; by the final build I owned 440 of its 509 lines - equip/reload/fire paths where the same component drives both player and enemy shooting from weapon ScriptableObjects, with ammo retained across weapon switches and restored from JSON.
  • Async scene loading (co-owned). The load routine handing scenes to a loading screen and the post-load pass that rebuilds a dictionary of every UniqueID object and restores inventory and scene state.

Debugging story: the save-triggered scene loop

The first time saving and scene-persistence went in together, loading a scene could re-trigger a save that re-triggered a load - an infinite loop two days before the milestone. Untangling save timing from scene transitions (and a boss that activated the moment the scene loaded, fixed on ship day) is documented right in the commit history.

process

Five per-developer branches merging through a shared Development branch into main - I synced Development into my branch 37 times in four weeks, which is what disciplined integration actually looks like under deadline. The team ran Scrum across Alpha, Beta, and QA sprint milestones. This project started as the P&P II FPS team project (also public on GitHub), continued by the same team.