Files
test/Documentation/MODEL_LOADING_FLOW.md
T
2026-03-13 16:03:47 +07:00

237 lines
9.8 KiB
Markdown

# 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<GameObject>()` 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