237 lines
9.8 KiB
Markdown
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
|
|
|