Files
DeviantMobile-Rohan/STEP_A_PROJECT_ANALYSIS.md

513 lines
34 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# STEP A — PROJECT ANALYSIS REPORT
## Deviant Mobile — Senior Unity Mobile Optimization Audit
---
## 1. PROJECT OVERVIEW
| Metric | Value |
|--------|-------|
| **Engine** | Unity 6 (URP 17.3.0) |
| **Platform** | Android (arm64-v8a) / iOS 15+ |
| **Genre** | 3v3 Fighting Game |
| **Game Modes** | Cash System (objective-based), Practice (deathmatch) |
| **Characters** | 6: Windham (Rabbit), Amira (Cheetah), Bahman (Eagle), Ziggy (Cat), Amon (Hammerhead), Imani (Hyena) |
| **C# Scripts** | 202 |
| **Prefabs** | 191 |
| **Materials** | 371 |
| **FBX Models** | 328 |
| **Shaders** | 42 |
| **Animation Files** | 3 (.anim) + 17 Animator Controllers in Resources |
| **Scene Files** | 154 total (80 recovery duplicates, 2 main) |
| **Total Assets Folder** | **28 GB** |
| **DEVIS (art source)** | **26 GB** (92.8% of project) |
| **Resources Folder** | 1.7 MB (6 character prefabs, 2 bags, 1 cash box, 17 animator controllers) |
---
## 2. ARCHITECTURE MAP
```
┌─────────────────────────────────────────────────────────────────────┐
│ SCENE: Main Menu │
│ ┌─────────────┐ ┌──────────────────┐ ┌──────────────────────┐ │
│ │ GameManager │ │ SelectionOptions │ │ CharacterPrefabMgr │ │
│ │ (Singleton) │ │ (DontDestroy) │ │ (DontDestroy) │ │
│ │ Mode/Audio │ │ Team data+sprites│ │ Name→Prefab path map │ │
│ └──────┬───────┘ └────────┬─────────┘ └──────────┬───────────┘ │
│ │ │ │ │
│ ┌──────┴──────────────────┴────────────────────────┴───────────┐ │
│ │ CharacterSelection / ModeSelection │ │
│ │ CashSystemCharacterSelection │ │
│ └───────────────────────────┬───────────────────────────────────┘ │
└──────────────────────────────┼──────────────────────────────────────┘
│ LoadScene("Game")
┌──────────────────────────────┼──────────────────────────────────────┐
│ SCENE: Game │
│ │
│ ┌────────────────────────────────────────────────────────────────┐ │
│ │ CORE INFRASTRUCTURE │ │
│ │ ┌─────────────┐ ┌──────────┐ ┌───────────────────────┐ │ │
│ │ │ GameEvents │ │ObjectPool│ │ EntityRegistry<T> │ │ │
│ │ │ 25 static │ │ Queue │ │ Static per-type lists │ │ │
│ │ │ Action<T> │ │ Generic │ │ FindNearest/Radius │ │ │
│ │ └──────────────┘ └──────────┘ └───────────────────────┘ │ │
│ └────────────────────────────────────────────────────────────────┘ │
│ │
│ ┌─────────────────────┐ ┌────────────────────────────────┐ │
│ │ CashSystemManager │────▶│ CashBagSpawner (ObjectPool) │ │
│ │ (Singleton, 1349L) │ │ CashBag (state machine) │ │
│ │ Timer, Spawning, │ │ CashCarrier (per-character) │ │
│ │ Switching, Win │ │ TeamVault (deposit/steal zone) │ │
│ │ BuzzerBeater │ │ CashBoxImportController │ │
│ └──────────┬──────────┘ └────────────────────────────────┘ │
│ │ │
│ ┌──────────┴──────────────────────────────────────────────────┐ │
│ │ CHARACTER LAYER (×6) │ │
│ │ ┌─────────────────┐ ┌──────────────────────┐ │ │
│ │ │ Player-Controlled│ │ AI-Controlled (×5) │ │ │
│ │ │ CharacterInput │ │ CharacterAIController│ │ │
│ │ │ CharacterMovement│ │ + CashSystemAI │ │ │
│ │ │ PlayerController │ │ + AIBrain (new) │ │ │
│ │ └────────┬─────────┘ └──────────┬───────────┘ │ │
│ │ │ │ │ │
│ │ ┌────────┴────────────────────────┴──────────────────┐ │ │
│ │ │ SHARED COMPONENTS │ │ │
│ │ │ HealthNew (1259L!) │ StaminaSystem │ │ │
│ │ │ CharacterMovement │ AnimationManager │ │ │
│ │ │ TeamMember │ CashCarrier │ │ │
│ │ │ EnemyTargetDetector │ FaceTargetOnAttack │ │ │
│ │ └─────────────────────────────────────────────────────┘ │ │
│ └──────────────────────────────────────────────────────────────┘ │
│ │
│ ┌──────────────────────────────────────────────────────────────┐ │
│ │ UI LAYER │ │
│ │ ┌────────────┐ ┌────────────┐ ┌───────────────────┐ │ │
│ │ │CashSystemUI│ │TeamHUDPanel│ │ Minimap System │ │ │
│ │ │ Timer,Vault│ │ Portraits │ │ MinimapManager │ │ │
│ │ │ KillFeed │ │ Health Dial│ │ MinimapMarker(s) │ │ │
│ │ │ Combo,Warn │ │ Switch tap │ │ EdgeIndicator │ │ │
│ │ └────────────┘ └────────────┘ └───────────────────┘ │ │
│ │ ┌────────────────┐ ┌─────────────────────┐ │ │
│ │ │ PreMatchIntroUI │ │ MatchResultUI │ │ │
│ │ │ 3v3 splash │ │ VICTORY/DEFEAT │ │ │
│ │ │ Countdown │ │ per-mode stats │ │ │
│ │ └────────────────┘ └─────────────────────┘ │ │
│ └──────────────────────────────────────────────────────────────┘ │
│ │
│ ┌─────────────────────┐ ┌────────────────────────────────────┐ │
│ │ Camera System │ │ Save System │ │
│ │ CameraFollow │ │ SaveManager (DontDestroy) │ │
│ │ CinemachineInput │ │ JsonDataService (XOR "encrypt") │ │
│ │ CameraShake │ │ GameData (wins/losses/rank/XP) │ │
│ └─────────────────────┘ └────────────────────────────────────┘ │
│ │
│ ┌─────────────────────────────────────────────────────────────┐ │
│ │ Asset Loading (Custom) │ │
│ │ RemoteAssetBundleManager → JSON catalog → bundle download │ │
│ │ AssetBundleDownloadManager → loading screen progress │ │
│ │ CustomAssetBundleSceneLoader → scene loader │ │
│ └─────────────────────────────────────────────────────────────┘ │
│ │
│ ┌───────────────────────────────────────┐ │
│ │ DISABLED: SpecialMoveCardSystem │ │
│ │ (CARD_SYSTEM_DISABLED = true) │ │
│ └───────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────────┘
```
---
## 3. SYSTEM-BY-SYSTEM ANALYSIS
### 3.1 MOVEMENT & AI SYSTEM
#### CharacterAIController (931 lines)
- **Pattern:** Coroutine-based decision loop (0.3s tick, 0.8s far tick) — good AI LOD
- **Strengths:** Distance-based decision throttling, NavMeshAgent-based, Camera.main cached at Awake
- **Concerns:**
- `FixedUpdate()` runs scale protection (`transform.localScale != originalScale`) every physics tick on every AI — workaround for FBX baked curves that should be fixed at import
- `cachedPlayerManager` declared but potentially never populated
#### EnemyAIController (270 lines) + TeamAIController (266 lines)
- **Pattern:** Separate coroutine-based controllers for enemy/ally AI
- **CRITICAL:** These appear **redundant** with `CharacterAIController` — three separate AI controller classes handling overlapping roles = maintenance nightmare
- **Concerns:** `Debug.Log` on every `OnEnable`/`OnDisable` — string allocation in production
#### CashSystemAI (741 lines)
- **Pattern:** Weighted utility scorer with AI roles (Balanced, Collector, Defender, Aggressor)
- **CRITICAL:** Coexists with `AIBrain` — the newer replacement system. Both gate on `isCashSystemSelected`. Unclear which is active at runtime.
- **Strengths:** 0.3s decision interval, state minimum duration preventing thrashing
#### AIBrain (353 lines) — NEW SYSTEM
- **Pattern:** Modular AI with `UtilityScorer`, `AIBlackboard`, `AIPerceptionSystem`, `AINavigationHelper`
- **Strengths:** 3-tier distance-based LOD ticking (0.3s / 0.5s / 1.0s), zero `FindObjectOfType`, pluggable actions
- **Concern:** Coexists with legacy `CashSystemAI` — migration incomplete
#### AIPerceptionSystem (242 lines)
- **Pattern:** Zero-alloc detection via `Physics.OverlapSphereNonAlloc`, memory system with `_lastKnownPositions`
- **Strengths:** Static shared collider buffer (safe in single-threaded Unity), FOV-filtered
- **Concern:** Static `Collider[32]` buffer — size is fine for 3v3 but architecture couples all instances
#### CharacterMovement (582 lines)
- **CRITICAL BUG:** Heavy use of **static fields** (`jump`, `jumpForce`, `gravity`, `isSprinting`, `turnSpeed`, `targetDirection`) — ALL CharacterMovement instances share the same values. Setting gravity for one character changes it for all 6. This is a **game-breaking bug** in 3v3 mode.
- **Concern:** Multiple `Debug.Log` including input values that could fire per-frame
- **Concern:** Dual input paths (legacy `PlayerScript` + new `CharacterInputHandler`) adds complexity
### 3.2 CASH SYSTEM
#### CashSystemManager (1349 lines) — GOD CLASS
- **CRITICAL:** `Update()` fires `GameEvents.FireTimerUpdated(matchTimer)` **EVERY FRAME**. All UI subscribers process this every frame. Should throttle to ~4Hz.
- **Concern:** 1349 lines handling spawning, timer, switching, win conditions, buzzer mechanic — massive SRP violation
- **Concern:** `Start()` creates multiple manager singletons via `new GameObject()` + `AddComponent()` — fragile order-dependent init
- **Concern:** 20+ `Debug.Log` calls with string interpolation
#### CashBagSpawner (345 lines) — CLEAN
- **Strengths:** Uses `ObjectPool` for zero-runtime allocation spawning, coroutine-based waves, `EntityRegistry` for distance checks
- **One of the cleanest classes in the codebase**
#### CashBag (416 lines)
- **Concern:** `Update()` runs idle animation (rotation+bobbing) every frame on every active bag (up to 15). Could use coroutine or be batched by spawner.
- **Concern:** Drop despawn timer uses per-frame deltaTime accumulation — coroutine would be cleaner
#### CashCarrier (375 lines)
- **Concern:** Dual cash tracking (`_legacyCash` float + `_carriedBags` list) — legacy compatibility dead weight
#### TeamVault (357 lines)
- **Strengths:** Coroutine-based magnet pulse (0.3s interval), event-driven deposit/steal notifications
- **No issues:** Clean implementation
#### CashBoxImportController (680 lines)
- **Concern:** 680 lines for an import animation — camera manipulation (reparenting, position override) is fragile and could conflict with CinemachineFollow
### 3.3 UI SYSTEM
#### CashSystemUI (643 lines)
- **Strengths:** Fully event-driven (14 GameEvents subscriptions), no polling, `_dirtyVault` flag for efficient LateUpdate
- **Concern:** 643 lines with 14+ event handlers — could be decomposed into TimerUI, ScoreUI, KillFeedUI, etc.
#### TeamHUDPanel (365 lines)
- **Concern:** Parallel list pattern (6 separate lists indexed together: portraits, health dials, backgrounds, name labels, dead overlays, highlight borders) — fragile. Should be a `TeamSlot` struct/class array.
- **Concern:** Likely Updates health dials per-frame on all team members — should be event-driven on `OnHealthChanged`
#### MatchResultUI (654 lines)
- **CRITICAL:** Sets `Time.fixedDeltaTime = 0f` to freeze physics. If scene reloads or restart is triggered without restoring this, **physics is permanently broken**.
- **Strengths:** Clean mode-specific stats display (Cash System vs Practice)
#### PreMatchIntroUI (430 lines)
- **Strengths:** Coroutine-driven, no per-frame cost when hidden
- **Uses sprites from SelectionOptions (recently fixed)**
#### MinimapManager (209 lines)
- **CONCERN:** Calls `FindObjectOfType<CashSystemManager>()` every ~1s via `FindPlayer()`. Should use `CashSystemManager.Instance` (singleton already exists).
### 3.4 CORE INFRASTRUCTURE
#### GameEvents (155 lines) — CRITICAL ARCHITECTURE
- **Strengths:** ~25 static `Action<T>` events with `?.Invoke()` — zero allocation pub/sub
- **CRITICAL:** **No event cleanup on scene unload.** Static events persist across scenes. If a subscriber is destroyed without unsubscribing, the delegate holds a reference to a destroyed object → `MissingReferenceException`. Needs a `ClearAll()` method called on scene transitions.
#### ObjectPool (290 lines)
- **Concern:** `PooledObject.Update()` runs every frame on every pooled object with `autoReturnDelay > 0` — adds up with many VFX pooled objects
- **Concern:** `ReturnAll()` creates `new List<GameObject>(_inUse)` — allocation during return operation
- **Concern:** `DontDestroyOnLoad` on pool containers means pools survive scene changes but references to scene objects become stale
#### EntityRegistry<T> (90 lines)
- **Strengths:** Generic static registry replacing `FindObjectsOfType`, O(1) register, O(n) queries
- **Concern:** `Register()` uses `List.Contains()` — O(n) dedup check on every register. Should use HashSet.
- **Concern:** Lambda predicates in `FindNearest`/`FindWithinRadius` may allocate closures if not cached
#### CharacterPrefabManager (206 lines)
- **Concern:** Hardcoded path strings (`"Rabbit"`, `"Cheetah"`) — should be data-driven via ScriptableObject
- **Note:** `aiPrefabPaths` dictionary may be redundant (comment says "AI NOW USES SAME UNIFIED PREFABS AS PLAYER")
#### GameManager (402 lines)
- **Concern:** Static `Instance` without clear `DontDestroyOnLoad` guard — possible double-instantiation
- **Concern:** Commented-out code blocks throughout — dead code
### 3.5 PLAYER SYSTEM
#### HealthNew (1259 lines) — **WORST GOD CLASS**
- **CRITICAL:** `Update()` runs every frame on **EVERY character** (6 in 3v3):
- Sets `healthSlider.value` even when health hasn't changed
- Calls `Camera.WorldToScreenPoint()` for AI health bar positioning every frame
- Checks particle VFX state based on health threshold per frame
- **CRITICAL:** 1259 lines mixing health logic, damage processing, health bar UI, death screen, reward screen, stamina, VFX — massive SRP violation
- **Concern:** `FindObjectOfType<PlayerManagerNew>()` in death/game-over paths
- **Concern:** 20+ `Debug.Log` calls
- **Concern:** `Instantiate(healthBarPrefab)` per character in Start without pooling
#### CharacterInputHandler (357 lines)
- **Strengths:** Enabled/disabled on character switch (only 1 active at a time), cached components
- **Concern:** Public fields (`block`, `dodge`, `attackEnabled`) without validation — external code can modify freely
### 3.6 COMBAT SYSTEM
#### EnemyTargetDetector (212 lines)
- **Strengths:** Zero-allocation design with pre-allocated collider buffer, `OverlapSphereNonAlloc`, FOV/LOS filtering — **excellent mobile practice**
#### FaceTargetOnAttack (254 lines)
- **Strengths:** `Update()` early-returns when `!assistActive` (near-zero idle cost), `HashSet<string>` for O(1) animation lookup, proper event subscribe/unsubscribe lifecycle
### 3.7 SAVE SYSTEM
#### SaveManager (176 lines)
- **Concern:** `async void` on `SaveGame()` and `InitializeSaveSystem()` — unobserved exceptions risk silent failures
- **Concern:** Each stat mutation (`AddWin`, `AddLoss`, `AddMatch`) triggers immediate save — no batching/debouncing
- **Dead code:** Server sync entirely commented out
#### JsonDataService (82 lines)
- **CONCERN:** XOR cipher with hardcoded key `"YOUR_ENCRYPTION_KEY"` — zero security
- **Concern:** Synchronous file I/O on main thread — small data but could hitch on slow storage
#### GameData (51 lines)
- **No schema versioning** — field changes break old saves silently
- **Mixes UI state** (`completed_missions_toAnimate`, `animation_status`) into persistent data
- **No currency/gem fields** — shop system unimplemented
### 3.8 ASSET LOADING
#### RemoteAssetBundleManager (664 lines)
- **Custom replacement for Unity Addressables** — JSON catalog from remote server, coroutine-based download
- **Concern:** Addressables package (2.8.1) still in manifest.json despite being fully replaced — wasted dependency
- **Strengths:** Configurable memory cleanup (`Resources.UnloadUnusedAssets + GC.Collect`), retry logic, stall detection
### 3.9 SPECIAL MOVE CARD SYSTEM
#### CardSpawner — `CARD_SYSTEM_DISABLED = true`
- **Entire subsystem is dead code** — the card system is globally disabled
- **No pooling** — cards use `Instantiate`/`Destroy` per spawn cycle
### 3.10 PLAYER MANAGEMENT
#### PlayerManagerNew (330 lines)
- **Concern:** `GameObject.Find("GameStatsManager")` in Awake — string-based lookup wrapped in try-catch swallowing errors
- **Concern:** `Update()` polls `retry` and `pause` bools every frame — should be event-driven
- **Mixes responsibilities:** gameplay state + audio settings + UI management
#### AnimationManager (319 lines)
- **Concern:** Uses **reflection** (`typeof(AnimationNames).GetFields()`) to auto-populate animation mappings — unnecessary when a static dictionary would suffice
- **Concern:** 50+ lines of manual animation name remapping — should be data-driven (SO/JSON)
---
## 4. CRITICAL PERFORMANCE ANTI-PATTERNS
### 🔴 SEVERITY: CRITICAL (fix immediately)
| # | Anti-Pattern | Location | Impact |
|---|---|---|---|
| 1 | **Static fields in CharacterMovement** shared across ALL instances | `CharacterMovement.cs` | Game-breaking: changing gravity/jump for one character affects all 6 |
| 2 | **Timer event fires every frame** | `CashSystemManager.Update()``GameEvents.FireTimerUpdated()` | All subscribers (CashSystemUI etc.) process every frame unnecessarily |
| 3 | **HealthNew.Update() on all 6 characters** sets slider, repositions bars, checks VFX | `HealthNew.cs` | 6× per-frame: Camera.WorldToScreenPoint + slider.value + VFX check |
| 4 | **Time.fixedDeltaTime = 0f never restored** | `MatchResultUI.Show()` | Physics permanently broken after match result if scene not fully reloaded |
| 5 | **No GameEvents.ClearAll() on scene transitions** | `GameEvents.cs` | MissingReferenceException on scene reload — delegates hold dead references |
### 🟠 SEVERITY: HIGH (fix before release)
| # | Anti-Pattern | Location | Impact |
|---|---|---|---|
| 6 | 26 GB DEVIS folder in project | `Assets/DEVIS/` | 92.8% of project size — should be excluded from version control and builds |
| 7 | 80 recovery scene duplicates | `Assets/_Recovery/` | 348 MB of dead scene files |
| 8 | 17 duplicate animator controllers in Resources | `Assets/Resources/` | All loaded into memory at build time (Resources folder = always included) |
| 9 | 50+ `Debug.Log` calls with string interpolation | Multiple files | GC allocation per log call on mobile; string.Format boxing |
| 10 | Addressables package still in manifest | `Packages/manifest.json` | Unused 2.8.1 dependency bloating build; conflicts with custom bundle system |
| 11 | PostProcessing v2 alongside URP | `Packages/manifest.json` | Redundant — URP has built-in Volume post-processing |
| 12 | Android Target SDK 30 | `ProjectSettings.asset` | Google Play requires API 34+ since Aug 2024 — **blocks store submission** |
| 13 | Gamma color space | `ProjectSettings.asset` | Incorrect lighting/HDR with URP; Linear required for physically-correct rendering |
| 14 | Engine code stripping disabled | `ProjectSettings.asset` | Significantly larger APK/AAB |
| 15 | GPU Skinning disabled | `ProjectSettings.asset` | 6 skinned characters = CPU skinning bottleneck on mobile |
### 🟡 SEVERITY: MEDIUM (optimize for performance)
| # | Anti-Pattern | Location | Impact |
|---|---|---|---|
| 16 | `FindObjectOfType<CashSystemManager>()` every ~1s | `MinimapManager.FindPlayer()` | Should use existing singleton Instance |
| 17 | `FindObjectOfType<PlayerManagerNew>()` in death paths | `HealthNew.cs` | Runtime lookup on critical path |
| 18 | `GameObject.Find("GameStatsManager")` in Awake | `PlayerManagerNew.cs` | String-based runtime lookup |
| 19 | `PooledObject.Update()` per-frame timer on all pooled objects | `ObjectPool.cs` | Per-frame cost scales with pool size |
| 20 | CashBag.Update() idle animation on 15 bags | `CashBag.cs` | 15 Update calls for visual-only bobbing |
| 21 | `EntityRegistry.Register()` uses List.Contains() | `EntityRegistry.cs` | O(n) dedup on every register call |
| 22 | Reflection for animation mapping | `AnimationManager.cs` | `typeof().GetFields()` in Awake — unnecessary |
| 23 | `GetComponent<InputToAnimation>()` per attack event | `PlayerController.cs` | Uncached component lookup on input event |
| 24 | 3 redundant AI controller classes | Multiple files | Maintenance burden: CharacterAIController, EnemyAIController, TeamAIController |
| 25 | SaveManager writes per stat mutation (no batching) | `SaveManager.cs` | Multiple rapid file writes after match end |
| 26 | `async void` on save methods | `SaveManager.cs` | Unobserved exception risk |
---
## 5. MISSING FEATURES / GAPS
| Feature | Status | Notes |
|---------|--------|-------|
| **Shop/Currency System** | ❌ Not implemented | Unity IAP (4.14.2) in manifest but no ShopManager code |
| **Online Multiplayer** | ❌ Not implemented | No Netcode/Photon/Mirror packages found |
| **Analytics Integration** | ⚠️ Package only | `com.unity.analytics` present but no custom event tracking in code |
| **Localization** | ❌ Not implemented | All strings hardcoded in English |
| **Accessibility** | ❌ Not implemented | No colorblind mode, no text scaling, no screen reader support |
| **Data Versioning** | ❌ Missing | `GameData` has no schema version field — save migration impossible |
| **Crash Reporting** | ❌ Not implemented | `mono_crash.mem.*.blob` files present in root — crashes happening but not tracked |
| **Performance Profiling Hooks** | ❌ Not implemented | No custom profiler markers, no frame budget tracking |
| **Memory Budget System** | ❌ Not implemented | No texture quality tiers, no LOD on models |
| **Loading Screen Tips** | ⚠️ Hardcoded | Hint strings in `AssetBundleDownloadManager` are not data-driven |
| **Tutorial/Onboarding** | ❌ Not found | No tutorial system scripts |
---
## 6. DEPENDENCY AUDIT
### Packages to REMOVE (unused/redundant):
| Package | Reason |
|---------|--------|
| `com.unity.addressables` 2.8.1 | Fully replaced by custom `RemoteAssetBundleManager` |
| `com.unity.addressables.android` 1.0.9 | Same — custom system replaces this |
| `com.unity.postprocessing` 3.5.1 | Redundant with URP Volume-based post-processing |
| `com.unity.visualscripting` 1.9.9 | No evidence of use in codebase |
| `com.unity.ai.assistant` + `.generators` + `.inference` + `.toolkit` | Pre-release AI tools — editor bloat |
### Packages to UPDATE:
| Package | Current | Required | Reason |
|---------|---------|----------|--------|
| `com.unity.cinemachine` | 2.10.5 | 3.x | CinemachineV2 is legacy; V3 has better mobile perf |
---
## 7. ASSET SIZE BREAKDOWN
```
Assets Total: 28.0 GB
├── DEVIS/ (art source): 26.0 GB ← 92.8% — MUST exclude from build
├── _Recovery/: 348 MB ← DELETE (80 duplicate scenes)
├── UI/: 234 MB
├── Future UI Sound Lib: 220 MB ← Audit: likely includes unused sounds
├── LowPoly Fantasy Bags: 131 MB
├── Scenes/: 89 MB ← 2 main scenes = 81 MB (40+41 MB each!)
├── Material/: 80 MB
├── New UI/: 60 MB
├── GooglePlayPlugins/: 43 MB
├── Hovl Studio/: 38 MB
├── Audio/: 23 MB
├── Hit & Slashes copy: 18 MB
├── Scripts/: 2.9 MB
├── Resources/: 1.7 MB
└── Everything else: ~5 MB
```
### Critical Asset Concerns:
1. **Scene files are 40+ MB each**`Game.unity` and `CITY_DONE.unity` are bloated. Likely contain embedded lightmaps, navigation data, or un-stripped mesh data.
2. **371 materials for a 6-character fighting game** — many are likely unused asset store imports.
3. **328 FBX models** — far more than needed for 6 characters + 1 arena. Audit for unused models.
4. **Textures >1MB:** PBR diffuse/normal maps up to 24 MB — uncompressed PNGs that should use ASTC compression on mobile.
5. **"Future UI Sound Library" (220 MB)** and **"Hit & Slashes Vol.3 copy" (18 MB)** — asset store packs likely containing mostly unused audio.
---
## 8. SINGLETON REGISTRY
| Singleton | Pattern | DontDestroyOnLoad | Notes |
|-----------|---------|-------------------|-------|
| `GameManager` | Manual static Instance | ⚠️ Unclear | May double-instantiate on scene reload |
| `SelectionOptions` | Manual static Instance | ✅ Yes | Carries team data + sprites cross-scene |
| `CharacterPrefabManager` | Manual static Instance | ✅ Yes | Name → prefab path map |
| `CashSystemManager` | Manual static Instance | ❌ No | Per-scene lifetime |
| `SaveManager` | Manual static Instance | ✅ Yes | File I/O |
| `UIManager` | Generic `Singleton<T>` base | ⚠️ Via base | Thin wrapper |
| `RemoteAssetBundleManager` | Lazy auto-creation | ✅ Yes | Can create orphans during shutdown |
| `PoolManager` | Manual static Instance | ✅ Yes | Pool registry |
**No service locator or DI container.** All inter-system communication is via:
1. Singleton references (`CashSystemManager.Instance`, etc.)
2. Static event bus (`GameEvents`)
3. `FindObjectOfType` / `GameObject.Find` (legacy patterns still present)
---
## 9. EVENT FLOW DIAGRAM
```
MATCH START
PreMatchIntroUI.Show()
┌──────────┴──────────┐
│ │
SpawnTeams() IntroSequence()
│ │
│ 3-2-1-FIGHT!
│ │
cashUI.ShowHUD() intro.IsComplete = true
┌─────────────────────────────────────────────┐
│ GAMEPLAY LOOP │
│ │
│ CashSystemManager.Update() │
│ ├── FireTimerUpdated(timer) ────────▶ CashSystemUI.OnTimerUpdated()
│ ├── FireScoreChanged(team,score) ───▶ CashSystemUI.OnScoreChanged()
│ ├── Check win threshold │
│ └── Check buzzer beater │
│ │
│ CashBagSpawner (wave coroutine) │
│ ├── Pool.Get() → CashBag │
│ └── EntityRegistry.Register(bag) │
│ │
│ CashBag ──OnTriggerEnter──▶ CashCarrier.AddBag()
│ ├── FireBagPickedUp() ──────▶ CashSystemUI pickup flash
│ └── FireBagPickedUp() ──────▶ MatchStatTracker.OnBagPickedUp()
│ │
│ TeamVault.MagnetPulse → Deposit │
│ ├── FireCashDeposited() ────▶ CashSystemUI vault bars
│ └── FireCashDeposited() ────▶ MatchStatTracker
│ │
│ HealthNew.TakeDamage() │
│ ├── FireDamageDealt() ──────▶ MatchStatTracker
│ └── Death → FireKill() ─────▶ CashSystemUI kill feed
│ │
│ Character Switch (tap TeamHUDPanel) │
│ └── FireCharacterSwitched() ──▶ CashSystemUI, Minimap
└──────────────────────┬──────────────────────┘
Timer expires / threshold hit
FireMatchResult(playerWon)
MatchResultUI.Show(playerWon)
├── Time.timeScale = 0
├── PopulateStats()
└── SaveManager.AddWin/Loss()
```
---
## 10. PRIORITY RANKING FOR OPTIMIZATION
### Tier 1 — Ship-Blocking (must fix before any build)
1. **Static fields in CharacterMovement** — game-breaking shared state
2. **Android Target SDK 30** — Google Play store rejection
3. **Time.fixedDeltaTime = 0f** not restored — breaks physics
4. **GameEvents.ClearAll() missing** — MissingReferenceException on scene reload
### Tier 2 — Performance-Critical (major FPS/memory impact)
5. **HealthNew God Class refactor** — 6× per-frame Update is the biggest performance drain
6. **Timer event throttling** — reduce `FireTimerUpdated` from 60Hz to 4Hz
7. **26 GB DEVIS folder** — exclude from build/VCS
8. **Delete _Recovery folder** — 348 MB of dead scenes
9. **Strip Debug.Log calls** — 50+ string allocations per frame on mobile
10. **Enable engine code stripping** — reduce APK size significantly
11. **Enable GPU Skinning** — offload 6-character skinning to GPU
12. **Switch to Linear color space** — correct URP lighting
### Tier 3 — Architectural Debt (prevents feature development)
13. Consolidate 3 AI controllers into 1 unified system
14. Complete AIBrain migration (remove CashSystemAI)
15. Refactor HealthNew into Health + HealthBarUI + DeathHandler
16. Add save data versioning
17. Remove unused packages (Addressables, PPv2, Visual Scripting)
18. Replace `FindObjectOfType` / `GameObject.Find` with singleton/registry
19. Audit 371 materials, 328 models, 191 prefabs for unused assets
20. Fix canvas reference resolution (7680×4320 is extreme for mobile)
---
*Report generated as part of the 6-step Mobile Optimization Engineering Audit.*
*Next: STEP B — Mobile Optimization Research (best practices, citations, benchmarks)*