Files
OGG/DEV_NOTES.md

12 KiB
Raw Permalink Blame History

OGG — Dev Notes & Systems Guide

Boomer shooter. Cruelty Squad vibes. Jank is a feature. This doc covers all current systems.


Scene Hierarchy

Player                      [CharacterController, FirstPersonController, SimpleCrosshair]
  │                         [Player, PlayerHUD, Inventory, WeaponManager, BootsEffect]
  └── Camera                [Camera, AudioListener, CameraShake, WeaponBob]

Pickups are standalone GameObjects placed anywhere in the scene — not children of the player.


Scripts Overview

Script Lives On What it does
FirstPersonController Player WASD move, mouse look, jump, sprint, cursor lock
Player Player Health + stamina stats, drain/regen logic, sprint gating
PlayerHUD Player Health bar, stamina bar, speedometer (IMGUI)
SimpleGun Weapon prefabs Shooting, ammo, recoil, muzzle flash, bullet decals
CameraShake Camera Singleton shake impulses, called by SimpleGun on fire
WeaponBob Camera Procedural weapon sway while moving
WeaponViewmodel Weapon prefabs Per-weapon position/rotation/scale in the player's hands
SimpleCrosshair Player Draws the crosshair via OnGUI
EnemyHealth Enemy objects Takes damage from SimpleGun raycasts, flashes red, dies
EnemySpawner Any object Spawns enemies at runtime
HumanoidEnemy Enemy objects Enemy AI / behaviour
ItemDefinition ScriptableObject asset Data definition for any item: name, icon, type, weapon prefab, equippable flag
PickupItem Pickup GameObjects Spin/bob animation, proximity prompt, E-to-collect
Inventory Player Item list, [I] HUD, right-click context menu, equip logic
WeaponManager Player Instantiates weapon prefabs, handles slot switching
BootsEffect Player Watches inventory for Bunny Hop Boots equipped state, applies stamina boost
StaminaBoostPickup Pickup GameObjects Legacy — superseded by BootsEffect. Left in for reference.

1. Player Stats — Player + PlayerHUD

Player.cs is the data container for all player stats. PlayerHUD.cs reads from it and draws the HUD.

Health fields:

  • maxHealth / health — enemies subtract from health directly, no auto-regen

Stamina fields:

  • maxStamina / stamina — depletes while sprinting
  • staminaDrain — units lost per second while sprinting (default 22)
  • staminaRegen — units gained per second when resting (default 12)
  • regenDelay — seconds of non-sprinting before regen starts (default 1.2)
  • When stamina hits 0 the player is exhausted — sprint locked out until stamina fully refills

HUD Layout:

[bottom-left corner]
SPEED
42.3
units / sec

HEALTH   85 / 100
[████████████░░░]
STAMINA  62 / 100
[██████░░░░░░░░░]

Speedometer:

  • Sits above the health/stamina bars, bottom-left
  • Speed calculated from actual position delta per frame (horizontal only)
  • Colour shifts: green → yellow → red as speed increases
  • Thresholds configurable in Inspector (speedoFastThreshold, speedoCritThreshold)
  • Can be toggled off via showSpeedometer bool

2. Movement — FirstPersonController

Standard FPS controller.

Inspector fields:

  • walkSpeed / runSpeed — intentionally high (50/80) due to CharacterController collision tuning
  • mouseSensitivity — linear, no acceleration
  • playerCamera — auto-found if empty, best to assign explicitly

Controls:

Key Action
W A S D / Arrows Move
Left Shift Sprint (drains stamina)
Space Jump
Mouse Look
Escape Unlock cursor
Left Click (unlocked) Re-lock cursor

3. Shooting — SimpleGun

Raycast-based hitscan. No projectiles.

Key fields:

  • damage — per shot
  • range — raycast distance in units
  • fireRate — shots per second
  • isAutomatic — hold vs click
  • recoilKickback / recoilKickUp — feel tuning
  • fpsCam — auto-found if null

Internals:

  • Muzzle flash: child Quad + Point Light, shown ~50ms per shot
  • Bullet decals: pooled (30 max), oldest reused when full
  • Spark particles: spawned and self-destroyed on impact
  • Calls CameraShake.Instance.Shake() on every shot
  • Shooting blocked when inventory is open
  • Position driven by WeaponManager.weaponPositionOffset each frame so recoil applies on top correctly

Ammo: currentAmmo / maxAmmo. Press R to reload (instant).


4. Item Definitions — ItemDefinition (ScriptableObject)

Create: Right-click in Project → Create → OGG → Item Definition

Field Notes
itemName Display name everywhere — must be unique
icon Sprite shown in inventory slots
type Misc, Consumable, or Weapon
isEquippable Tick for non-weapon items that can be equipped (e.g. boots) — shows equip button in inventory
weaponPrefab Weapon type only — prefab spawned in weapon holder when equipped
description Shown in inventory detail panel

5. Pickups — PickupItem

Attach to any GameObject to make it a spinning, bobbing pickup.

Setup:

  1. Place a GameObject in the scene with any mesh
  2. Add PickupItem component
  3. Drag an ItemDefinition into the Definition slot

Inspector fields:

Field Notes
definition The ItemDefinition asset
spinSpeed Degrees/sec Y rotation (default 120)
bobHeight Vertical travel in units (default 0.18)
bobSpeed Bob cycles per second (default 2.2)
pickupRadius Proximity trigger distance
pickupKey Default E
pickupParticlesPrefab Optional — spawned on collect
pickupSound Optional — played on collect

On pickup: Calls Inventory.AddItem(definition, autoEquip: true) — picking up a weapon automatically equips it.


6. Inventory — Inventory

Lives on the Player. Press I to open/close. Cursor unlocks when open.

HUD Layout:

┌──────────────────────────────┐
│       [ INVENTORY ]          │  ← header, shows active weapon top-right
├──────────────────────────────┤
│ [  ] [  ] [  ] [  ]         │
│ [  ] [  ] [  ] [  ]         │  ← item grid (4×5 by default)
├──────────────────────────────┤
│ SELECTED: Item Name          │  ← detail panel
│ Description                  │
│ ▶ EQUIPPED      [ F ] UNEQUIP│  ← shown for weapons AND equippable items
└──────────────────────────────┘

Right-click context menu on any slot:

  • Equip / Unequip — shown for weapons and items with isEquippable = true
  • Inspect — selects the item in the detail panel
  • Drop — removes from inventory

Controls:

Input Action
I Toggle inventory open/close
Click slot Select item
Double-click weapon slot Equip it
Right-click slot Open context menu
F Equip selected item
Scroll Wheel (closed) Cycle weapons
19 (closed) Equip weapon by slot number

Slot colours:

  • Dark grey = empty
  • Dark green = has item
  • Bright green = selected
  • Orange = equipped

Useful methods:

inventory.HasItem("Medkit")           // bool
inventory.CountOf("Grenade")          // int
inventory.RemoveItem("Medkit", 1)     // bool
inventory.AddItem(definition)         // add by ItemDefinition
inventory.AddItem("Raw Name", sprite) // add by name
inventory.IsOpen                      // bool — checked by gun + WeaponManager

7. Weapon Manager — WeaponManager

Lives on the Player. Manages weapon instances and which is active.

Setup:

  • Add WeaponManager to Player
  • Set Weapon Holder to the Camera transform
  • Any SimpleGun child of the holder is auto-registered but starts inactive — player must pick up and equip from inventory

Weapon Position fields:

  • weaponPositionOffset / weaponRotationOffset / weaponScale — global fallback if the weapon has no WeaponViewmodel component
  • Per-weapon positioning is preferred — add WeaponViewmodel to the weapon prefab instead

Live positioning workflow (in Editor):

  1. Hit Play, equip the gun
  2. On WeaponManager Inspector → click "Select Active Weapon in Scene"
  3. Use gizmos in Scene view to position it
  4. Click "Sync Transform → Offset Fields" — saves to the WeaponViewmodel on the prefab automatically
  5. Stop Play — values persist

Useful methods:

weaponManager.EquipByIndex(0)
weaponManager.EquipByName("Gun Splat")
weaponManager.CycleWeapon(1)           // next
weaponManager.CycleWeapon(-1)          // previous
weaponManager.ActiveWeaponName         // string
weaponManager.Unequip()                // holster all

8. WeaponViewmodel — WeaponViewmodel

Add to a weapon prefab to define how it sits in the player's hands. WeaponManager reads from it on equip instead of using the global offset.

Fields:

  • positionOffset — local position relative to weapon holder
  • rotationOffset — euler angles
  • scale — local scale

Each weapon prefab gets its own values, so Gun Splat can sit differently from any future weapon.


9. Equippable Items — BootsEffect

Add BootsEffect to the Player for the Bunny Hop Boots to work.

Lives on the Player. Watches Inventory.items each frame for the boots' isEquipped state and adjusts Player.maxStamina accordingly.

State Effect
Boots equipped maxStamina → 200, stamina topped up
Boots unequipped maxStamina → 100, stamina clamped back down

The stamina bar stretches/shrinks live to reflect the new max.

Inspector fields:

  • bootsItemName — must match the ItemDefinition itemName exactly (default "Bunny Hop Boots")
  • boostedMaxStamina — default 200

Setup Scripts (Editor Menu: OGG → Setup)

Create Gun Splat Weapon

Creates:

  • Assets/Prefabs/Weapons/GunSplat.prefab — held weapon with SimpleGun
  • Assets/Prefabs/Pickups/GunSplat_Pickup.prefab — world pickup with spin/bob
  • Assets/Items/GunSplat_Item.assetItemDefinition (type = Weapon)

Create Bunny Hop Boots

Creates:

  • Assets/Items/BhopBoots_Item.assetItemDefinition (type = Misc, isEquippable = true)
  • Assets/Prefabs/Pickups/BhopBoots_Pickup.prefab — world pickup

After running either script: drag the pickup prefab into your scene.


Adding a New Weapon — Step by Step

  1. Create an ItemDefinition asset — set type = Weapon, assign your gun prefab to weaponPrefab
  2. Add SimpleGun to the gun prefab root
  3. Add WeaponViewmodel to the gun prefab — set position/rotation/scale or dial it in with the live Editor workflow
  4. Create a pickup: any mesh + PickupItem component + drag in the ItemDefinition
  5. Place the pickup in the scene

Adding a New Equippable Item

  1. Create an ItemDefinition — set type = Misc, tick isEquippable = true
  2. Write a component that lives on the Player, watches inventory.items for entry.isEquipped, and applies/removes the effect
  3. Place a pickup in the scene referencing the definition

Adding a Consumable

Inventory inv = GetComponent<Inventory>();
if (inv.HasItem("Medkit")) {
    health += 50f;
    inv.RemoveItem("Medkit");
}

Known Rough Edges

  • No weapon switch animation — instant swap. Hook into WeaponManager.EquipByIndex() when ready.
  • No save system — inventory is runtime only, nothing persists between sessions.
  • Starting gun — any SimpleGun that's a child of the Camera at Start gets auto-registered but starts inactive. Player needs to find it as a pickup in the scene.
  • Inventory is IMGUI — not Canvas. Performance fine at this scale. All data logic is decoupled from drawing so a Canvas swap later would be straightforward.
  • SimpleGun assumes it's always active — non-SimpleGun weapons will slot-switch fine but need their own input handling to shoot.

Controls Reference

Key Action
W A S D Move
Left Shift Sprint
Space Jump
Left Click Shoot
Right Click Context menu (inventory open)
R Reload
E Pick up nearby item
I Open / close inventory
F Equip selected item
Scroll Wheel Cycle weapons
1 9 Equip weapon by slot
Escape Unlock cursor