> For the complete documentation index, see [llms.txt](https://dante-3.gitbook.io/dante-docs/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://dante-3.gitbook.io/dante-docs/modular-attachment-system/modular-attachment-subsystem/three-phase-load-pipeline.md).

# Three-Phase Load Pipeline

The subsystem orchestrates all asset streaming through FStreamableManager (not UAssetManager primary asset loading). This means no AssetManager registration is required for the pipeline to work — only

```
Component→LoadAttachment()
  │
  ▼
Subsystem→RequestLoad(DefinitionSoftPtr, Component)
  │
  ├─ Phase 1: Stream the definition data asset
  │    FStreamableManager::RequestAsyncLoad(DefinitionPath)
  │    └─► OnDataAssetLoaded()
  │
  ├─ Phase 2: Stream all fragment soft refs (batch)
  │    Definition→CollectAllSoftRefs() → TArray<FSoftObjectPath>
  │    FStreamableManager::RequestAsyncLoad(AllSoftRefs, HighPriority)
  │    └─► OnFragmentAssetsLoaded()
  │
  └─ Phase 3: Apply to all waiting components
       For each Component in Entry.Waiters:
         Component→OnAttachmentLoadFinished(Definition)
           └─ Component→ApplyFragmentTree() ×N
```

### Ref-Counted Cache

The cache is keyed by `FSoftObjectPath` (the definition's asset path):

```cpp
TMap<FSoftObjectPath, FAttachmentCacheEntry> AssetCache;
```

| Field      | Type                                                  | Description                                               |
| ---------- | ----------------------------------------------------- | --------------------------------------------------------- |
| `Handle`   | `TSharedPtr<FStreamableHandle>`                       | Streaming handle for the definition + all fragment assets |
| `RefCount` | `int32`                                               | Number of components using this definition                |
| `State`    | `EAttachmentLoadState`                                | Current state of this cache entry                         |
| `Waiters`  | `TArray<TWeakObjectPtr<UModularAttachmentComponent>>` | Components waiting for load completion                    |

When `RefCount` reaches zero, the entry is **not destroyed immediately** — a deferred unload is scheduled for the next tick to prevent mid-frame destruction.

### Already-Loaded Fast Path

If a component requests a definition that is already `Loaded` in the cache, `OnAttachmentLoadFinished` is called **synchronously** — no async wait, no frame delay.
