chunk 0: bootstrap config and project settings
This commit is contained in:
512
STEP_A_PROJECT_ANALYSIS.md
Normal file
512
STEP_A_PROJECT_ANALYSIS.md
Normal file
@@ -0,0 +1,512 @@
|
||||
# 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)*
|
||||
Reference in New Issue
Block a user