QORPO Blog / Development

Unreal asset loading: plan for the moment the player needs it

Q
QORPO Studio21 October 2026 · 7 min read
Miniature landscape modules join a coherent island on a developer desk
Concept illustration created for this article, not a gameplay screenshot.

Asynchronous loading moves an asset request away from an immediate blocking wait, but it does not decide when the asset should arrive or what the player sees until then. A reliable loading plan combines reference choices, a readiness state, a useful fallback and measurements from a packaged build. Replacing a hard reference with a soft one is only part of the work.

This is an engineering guide with illustrative examples, not a claim that a particular QORPO game has achieved a measured frame-time improvement. For the wider studio context, see what QORPO is. The acceptance approach complements our guide to production-ready build evidence.

Begin with the player's next action

Start at the moment the player needs the asset. A creature portrait might be needed when its card opens. A character mesh might be needed before a transformation becomes visible. A new environment may need several systems ready before the player can enter. These requests have different deadlines and different acceptable fallbacks.

An inventory portrait can sometimes use a clear placeholder briefly. A playable character cannot safely become an invisible body because the mesh is still loading. Nor should the game accept an action whose essential feedback has not arrived. Define the experience first, then select a loading strategy that can support it.

Write down the consequence of lateness. Does the player wait in a menu, remain in the current form or see an unavailable action? That decision belongs in the product flow. It should not emerge accidentally from whichever callback happens to finish last.

Hard and soft references answer different questions

Epic's asset reference documentation distinguishes direct hard references from indirect soft references. A hard dependency can cause another asset to load with its owner. A soft reference identifies an asset without making the same immediate loading commitment.

Neither is automatically the correct choice everywhere. A small resource that is always needed with its owner may not benefit from an elaborate request lifecycle. Optional cosmetic content or a large collection of rarely opened portraits may justify more explicit loading boundaries.

Inspect the dependency relationship, not just the field type. An apparently lightweight object can lead to other resources through its dependencies. Changing one reference is not proof that the whole chain has become smaller. Verify the actual resources involved and compare behaviour on a representative build.

Model readiness explicitly

An illustrative asset request can move through not requested, loading, ready, failed and no longer needed. These names describe an application-level decision, not a mandatory Unreal class. Their value is that the team can discuss what happens in every state.

In the loading state, a menu may show a neutral placeholder and keep navigation available. In the ready state, it can replace that placeholder. In the failed state, it needs a response that does not falsely suggest ownership, deletion or a successful action. If the user closes the menu, the completion callback must not re-open it.

Keep the request's identity separate from the visible screen's lifetime. A fast sequence of selections can produce several requests whose completion order differs from the input order. The latest visible selection should win because the application checks it, not because the team hopes the requests complete conveniently.

Request before the deadline, not just before display

Epic's asynchronous asset loading guide explains mechanisms for requesting assets without the same synchronous loading pattern. It gives the engine tools, but the game still needs to choose the request time.

In a model menu, focusing a card might be an appropriate time to request its larger preview. Loading every preview on entry defeats the point if most cards are never opened. Waiting until after the player confirms may be too late. The right boundary depends on resource size, navigation speed and the cost of being wrong.

For a world transition, identify which assets are essential to enter and which can arrive later. Do not put a decorative object and a collision-critical object into the same readiness category merely because they belong to the same environment. The player experiences their absence differently.

Completion is not the end of resource ownership

An asynchronous operation needs a clear owner. Decide who keeps the loaded resource available, which views may reuse it and when it can be released. A callback firing does not explain the resource's intended lifetime.

The application should also handle the owner disappearing during the request. A screen can close, a level can change or a player can leave a session. The completion path must check that its destination is still valid. Otherwise, a loading optimisation can become a source of stale updates and difficult-to-reproduce failures.

Avoid solving every case with permanent retention. Keeping everything forever can make subsequent interactions appear fast while hiding growing memory use. Measure a complete loop, including repeated entry and exit, rather than only the most flattering second visit.

Measure a cold path and a repeated path

A warm editor session is not the same as a fresh packaged run. Resources may already be resident after development activity. Record the conditions of each measurement so a faster second attempt is not mistaken for a code improvement.

A practical comparison follows the same user route on the same representative hardware. Capture frame time, memory behaviour and the time until the required visual state is usable. Include both a fresh start and repeated navigation. State whether the measurement concerns a menu, a level transition or a gameplay action.

Do not publish a percentage improvement without the baseline and method. Even an honest local result may not transfer to slower storage, another graphics configuration or a different content set. Treat the result as evidence for the tested scenario and expand testing when the product's supported conditions require it.

Test the awkward sequences

Rapidly open and close the preview. Change selection before loading completes. Leave the level. Request the same asset from two views. Trigger a failure in a controlled test environment. Then check whether the visible result still matches the current user action.

Also examine an action that becomes available before the art finishes loading. Can the player confirm it? Is that confirmation meaningful? If a preview is optional but an effect is essential to understanding combat, they should not share a blanket rule.

These sequences are useful because they test the contract around loading rather than the happy-path mechanism alone. A method returning successfully does not establish that the experience remains coherent through cancellation, navigation and failure.

Where AI assistance can help

AI can help enumerate states, draft test cases or flag direct loads for a developer to inspect. It cannot establish that a packaged route is smooth simply by reading code. Keep the model's suggestions distinct from measured observations.

A good AI-assisted task is narrow: inspect one preview flow, identify its owner and list what happens if the screen closes. A vague request to make the whole game stream better is difficult to review and easy to overstate. Our AI code review checklist explains how to keep that boundary practical.

For a product-specific view of development evidence, read the AneeMate October update. A player should see dependable transitions and clear feedback; the engineering record should explain which conditions actually support that experience.

Questions developers often ask

Does a soft reference guarantee asynchronous loading?

No. The reference choice and the loading operation are separate decisions. Inspect how the resource is requested and consumed rather than assuming the field type alone determines runtime behaviour.

Should every menu image be loaded in advance?

Only when the usage pattern and measurements justify it. Preparing everything may trade visible waiting for unnecessary work and memory. Define a small, useful readiness boundary and measure the route that players actually follow.

Is a successful callback proof that the player can proceed?

Not by itself. The destination still needs to be valid, the requested asset needs to match the current action and all other required systems need to be ready. Make that decision explicit in the product flow.