34 KiB
34 KiB
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 importcachedPlayerManagerdeclared 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.Logon everyOnEnable/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 onisCashSystemSelected. 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.Logincluding input values that could fire per-frame - Concern: Dual input paths (legacy
PlayerScript+ newCharacterInputHandler) adds complexity
3.2 CASH SYSTEM
CashSystemManager (1349 lines) — GOD CLASS
- CRITICAL:
Update()firesGameEvents.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 vianew GameObject()+AddComponent()— fragile order-dependent init - Concern: 20+
Debug.Logcalls with string interpolation
CashBagSpawner (345 lines) — CLEAN
- Strengths: Uses
ObjectPoolfor zero-runtime allocation spawning, coroutine-based waves,EntityRegistryfor 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 (
_legacyCashfloat +_carriedBagslist) — 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,
_dirtyVaultflag 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
TeamSlotstruct/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 = 0fto 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 viaFindPlayer(). Should useCashSystemManager.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 aClearAll()method called on scene transitions.
ObjectPool (290 lines)
- Concern:
PooledObject.Update()runs every frame on every pooled object withautoReturnDelay > 0— adds up with many VFX pooled objects - Concern:
ReturnAll()createsnew List<GameObject>(_inUse)— allocation during return operation - Concern:
DontDestroyOnLoadon pool containers means pools survive scene changes but references to scene objects become stale
EntityRegistry (90 lines)
- Strengths: Generic static registry replacing
FindObjectsOfType, O(1) register, O(n) queries - Concern:
Register()usesList.Contains()— O(n) dedup check on every register. Should use HashSet. - Concern: Lambda predicates in
FindNearest/FindWithinRadiusmay allocate closures if not cached
CharacterPrefabManager (206 lines)
- Concern: Hardcoded path strings (
"Rabbit","Cheetah") — should be data-driven via ScriptableObject - Note:
aiPrefabPathsdictionary may be redundant (comment says "AI NOW USES SAME UNIFIED PREFABS AS PLAYER")
GameManager (402 lines)
- Concern: Static
Instancewithout clearDontDestroyOnLoadguard — 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.valueeven 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
- Sets
- 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.Logcalls - 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 voidonSaveGame()andInitializeSaveSystem()— 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/Destroyper 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()pollsretryandpausebools 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:
- Scene files are 40+ MB each —
Game.unityandCITY_DONE.unityare bloated. Likely contain embedded lightmaps, navigation data, or un-stripped mesh data. - 371 materials for a 6-character fighting game — many are likely unused asset store imports.
- 328 FBX models — far more than needed for 6 characters + 1 arena. Audit for unused models.
- Textures >1MB: PBR diffuse/normal maps up to 24 MB — uncompressed PNGs that should use ASTC compression on mobile.
- "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:
- Singleton references (
CashSystemManager.Instance, etc.) - Static event bus (
GameEvents) 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)
- Static fields in CharacterMovement — game-breaking shared state
- Android Target SDK 30 — Google Play store rejection
- Time.fixedDeltaTime = 0f not restored — breaks physics
- GameEvents.ClearAll() missing — MissingReferenceException on scene reload
Tier 2 — Performance-Critical (major FPS/memory impact)
- HealthNew God Class refactor — 6× per-frame Update is the biggest performance drain
- Timer event throttling — reduce
FireTimerUpdatedfrom 60Hz to 4Hz - 26 GB DEVIS folder — exclude from build/VCS
- Delete _Recovery folder — 348 MB of dead scenes
- Strip Debug.Log calls — 50+ string allocations per frame on mobile
- Enable engine code stripping — reduce APK size significantly
- Enable GPU Skinning — offload 6-character skinning to GPU
- Switch to Linear color space — correct URP lighting
Tier 3 — Architectural Debt (prevents feature development)
- Consolidate 3 AI controllers into 1 unified system
- Complete AIBrain migration (remove CashSystemAI)
- Refactor HealthNew into Health + HealthBarUI + DeathHandler
- Add save data versioning
- Remove unused packages (Addressables, PPv2, Visual Scripting)
- Replace
FindObjectOfType/GameObject.Findwith singleton/registry - Audit 371 materials, 328 models, 191 prefabs for unused assets
- 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)