# Model Loading Flow: C++ to C# Conversion This document maps the C++ model loading sequence to the C# Addressables-based implementation. ## C++ Version Flow ``` 1. INITIALIZATION ┌─────────────────────────┐ │ CECPlayer Constructor │ │ memset(m_pModels, 0) │ └───────────┬───────────────┘ │ ▼ 2. LOAD REQUEST ┌─────────────────────────┐ │ LoadPlayerSkeleton() │ └───────────┬───────────────┘ │ ┌───────┴───────┐ │ │ ▼ ▼ Synchronous Asynchronous │ │ │ ▼ │ ┌────────────────────┐ │ │ QueueECModelForLoad │ │ │ (Background Thread)│ │ └───────────┬────────┘ │ │ │ ▼ │ ┌────────────────────┐ │ │ ThreadLoadPlayerModel│ │ └───────────┬────────┘ │ │ │ ▼ │ ┌────────────────────┐ │ │ m_aLoadedModels.Add │ │ └───────────┬────────┘ │ │ │ ▼ │ ┌────────────────────┐ │ │ DeliverLoadedModels │ │ │ (Every Frame Tick) │ │ └───────────┬────────┘ │ │ └──────────────────┘ │ ▼ 3. MODEL CREATION ┌─────────────────────────┐ │ LoadPlayerModel() │ │ - new CECModel │ │ - Load model file │ │ - Load skins/equips │ └───────────┬───────────────┘ │ ▼ 4. MODEL ASSIGNMENT ┌─────────────────────────┐ │ SetPlayerLoadedResult() │ │ - m_pPlayerModel = ... │ │ - m_pModels[MAJOR] = ...│ └─────────────────────────┘ ``` ## C# Version Flow (Using Addressables) ``` 1. INITIALIZATION ┌─────────────────────────┐ │ CECPlayer.Awake() │ │ - m_aEquips = new int[] │ │ - m_iShape = 0 │ │ (No memset needed) │ └───────────┬───────────────┘ │ ▼ 2. LOAD REQUEST ┌─────────────────────────┐ │ CECHostPlayer.InitCharacter() │ │ - LoadResources() │ │ - SetPlayerModel() │ └───────────┬───────────────┘ │ ┌───────┴───────┐ │ │ ▼ ▼ LoadResources() SetPlayerModel() │ │ ▼ ▼ ┌──────────────┐ ┌──────────────────────┐ │LoadPlayerSkeleton│ │NPCManager.GetModelPlayer│ └───────┬──────┘ └──────────┬───────────┘ │ │ ▼ ▼ ┌──────────────┐ ┌──────────────────────────┐ │SetPlayerLoadedResult│ │AddressableManager.LoadPrefabAsync│ └───────┬──────┘ └──────────┬───────────────┘ │ │ ▼ │ ┌──────────────┐ │ │OnAllResourceReady│ │ └──────────────┘ │ │ ▼ ┌──────────────────────┐ │ Unity Addressables │ │ LoadAssetAsync() │ │ (Async/Await) │ └──────────┬───────────┘ │ ▼ ┌──────────────────────┐ │ Instantiate(prefab) │ │ SetParent() │ │ SetActive(true) │ └──────────────────────┘ ``` ## Key Differences ### 1. Initialization **C++:** - `memset(m_pModels, 0)` - Zero-initializes model array **C#:** - `Awake()` method initializes arrays: ```csharp m_aEquips = new int[(int)IndexOfIteminEquipmentInventory.SIZE_ALL_EQUIPIVTR]; m_iShape = 0; ``` - Location: `Assets/PerfectWorld/Scripts/Move/CECPlayer.cs:186-192` ### 2. Load Request Entry Point **C++:** - `LoadPlayerSkeleton()` directly calls `LoadPlayerModel()` or `QueueECModelForLoad()` **C#:** - `LoadPlayerSkeleton()` is simplified and mostly commented out - Actual loading happens in `InitCharacter()` → `SetPlayerModel()` - Location: `Assets/Scripts/CECHostPlayer.cs:1173-1175` ### 3. Asynchronous Loading Mechanism **C++:** - Background thread: `QueueECModelForLoad()` → `ThreadLoadPlayerModel()` - Queue system: `m_aLoadedModels.Add()` - Frame-based delivery: `DeliverLoadedModels()` called every frame tick **C#:** - **No background thread** - Uses Unity's async/await pattern - **No queue system** - Direct async/await handling - **No frame-based delivery** - Completion handled by async/await - Flow: `SetPlayerModel()` → `NPCManager.GetModelPlayer()` → `AddressableManager.LoadPrefabAsync()` - Location: `Assets/PerfectWorld/Scripts/Move/CECPlayer.cs:195-209` ### 4. Model Loading Implementation **C++:** - `LoadPlayerModel()` creates `CECModel`, loads model file, loads skins/equips **C#:** - `NPCManager.GetModelPlayer()` loads model via Addressables: ```csharp var prefab = await AddressableManager.Instance.LoadPrefabAsync(_playerModelPaths[profession * GENDER.NUM_GENDER + gender]); var player = Instantiate(prefab); ``` - Location: `Assets/PerfectWorld/Scripts/Managers/NPCManager.cs:101-113` ### 5. Addressables System **C# Implementation:** - `AddressableManager` wraps Unity Addressables API - Uses `Addressables.LoadAssetAsync()` internally - Caches loaded assets in `_loadedPrefabAssets` dictionary - Location: `Assets/PerfectWorld/Scripts/Addressable/AddressableManager.cs:135-170` ### 6. Model Assignment **C++:** - `SetPlayerLoadedResult()` assigns: - `m_pPlayerModel = ...` - `m_pModels[MAJOR] = ...` **C#:** - Model assignment happens directly in `SetPlayerModel()`: ```csharp _pPlayerModel = await NPCManager.Instance.GetModelPlayer(profession, gender); _pPlayerModel.transform.SetParent(parentModel); _pPlayerModel.transform.localPosition = Vector3.zero; _pPlayerModel.SetActive(true); ``` - Location: `Assets/PerfectWorld/Scripts/Move/CECPlayer.cs:203-208` - `SetPlayerLoadedResult()` only calls `OnAllResourceReady()` (simplified) - Location: `Assets/Scripts/CECHostPlayer.cs:375-378` ## Code Locations Summary ### C# Files: 1. **CECPlayer.cs** (Base class) - `Awake()`: Initialization - `SetPlayerModel()`: Main model loading entry point - Location: `Assets/PerfectWorld/Scripts/Move/CECPlayer.cs` 2. **CECHostPlayer.cs** (Host player implementation) - `LoadResources()`: Entry point for resource loading - `LoadPlayerSkeleton()`: Simplified skeleton loading (mostly commented) - `SetPlayerLoadedResult()`: Simplified result handler - `InitCharacter()`: Calls LoadResources() and SetPlayerModel() - Location: `Assets/Scripts/CECHostPlayer.cs` 3. **NPCManager.cs** (Model provider) - `GetModelPlayer()`: Loads model via Addressables - Location: `Assets/PerfectWorld/Scripts/Managers/NPCManager.cs` 4. **AddressableManager.cs** (Addressables wrapper) - `LoadPrefabAsync()`: Core Addressables loading method - Location: `Assets/PerfectWorld/Scripts/Addressable/AddressableManager.cs` 5. **CECHostPlayer.Model.cs** (Shape transformation) - `TransformShape()`: Handles shape changes - `QueueLoadDummyModel()`: Referenced but implementation may be elsewhere - Location: `Assets/Scripts/CECHostPlayer.Model.cs` ## Notes - The C# version **removed the background thread loading system** in favor of Unity's async/await pattern - The **queue-based delivery system** (`DeliverLoadedModels`) is replaced by async/await completion handlers - **Addressables** provide built-in caching and memory management, eliminating the need for manual queue management - Some C++ methods like `LoadPlayerModel()` and `QueueLoadDummyModel()` are **commented out** in the C# version, suggesting they may be refactored or replaced - The model loading is now **more streamlined** with direct async calls rather than a multi-step queue system