If you've ever wondered why your project takes 90 seconds to load a level that only has 3 actors visible, this post is for you. The answer is almost always: hard references pulling the entire content of your game into memory.

Let's fix that.

What's a reference, anyway?

In Unreal, when one asset points to another asset, that's a reference. Your BP_PlayerCharacter references its mesh. Your BP_Pickup_HealthPotion references the potion mesh, the sound effect, the particle effect.

There are two ways to express that pointer:

  • Hard reference (Object Reference / Class Reference): Unreal loads the target into memory as soon as the referencing asset is loaded.
  • Soft reference (Soft Object Reference / Soft Class Reference): Unreal just stores the path to the target. It only loads when you ask it to.

Same blueprint pin, very different memory cost.

A concrete example

You're building an inventory system. You have a BP_Item_Base Blueprint, and 200 child items: weapons, potions, scrolls, ingredients.

In your BP_Player, you have an array variable: Items : BP_Item_Base[].

That's a hard array reference. The instant BP_Player loads, all 200 item Blueprints load too. Plus their meshes. Plus their textures. Plus their sound effects. Welcome to your 90-second load time.

Change the array type to Items : Soft Class Reference (BP_Item_Base)[] and the player now stores 200 paths. Total cost: maybe 8 KB. Items load only when actually picked up.

That's the difference.

When should I use each?

Use hard references when:

  • The object is used every frame (your player mesh, the HUD).
  • The object is always present anyway (a global manager).
  • The reference is a one-off and small.

Use soft references when:

  • The object is conditional — picked up, spawned, opened.
  • The object is big (meshes, sounds, particle systems).
  • You have many of them in a list (item catalogues, dialogue trees, enemy spawn tables).

Rule of thumb: if you can't honestly say "this object is needed right now, every time this asset loads", make it soft.

How to load a soft reference

Hard refs are automatic — nothing to do. Soft refs need one node:

CB0

That's Async Load Asset (for Soft Object Reference) or Async Load Class Asset (for Soft Class Reference). The OnLoaded execution pin fires once the asset is in memory.

The cost: one extra node and a tiny async wait the first time. The benefit: your level loads 10× faster.

Common pitfalls

  • Casting to a soft-referenced class without loading first. The cast will fail silently. Load first, then cast.
  • Storing soft refs in a tight loop. If you Async Load Asset inside a Tick event you're re-loading every frame. Load once, store the result.
  • Forgetting to keep a reference to the loaded object. Once the load finishes, store the result in a variable. If you don't, Unreal garbage-collects the asset and you'll load it again next time.
  • Mixing patterns. If even one node in your reference chain is a hard reference, everything past it gets pulled in. Trace the chain.

How to find your hard-ref problems

Unreal has a built-in tool. Right-click any asset → Reference Viewer (or press Alt+Shift+R). You'll see exactly what loads when this asset is touched. If your BP_Player has 400 things hanging off it, that's where to start.

For a project-wide audit: Window → Developer Tools → Size Map. Pick a class, see its memory footprint and what's pulling it in.

The 30-second recap

  • Hard reference = loads immediately, always, fully.
  • Soft reference = loads only when you ask.
  • Big, optional, or many → soft.
  • Always-present and tiny → hard.
  • Reference Viewer (Alt+Shift+R) shows you the truth.

Try it: open the most-loaded asset in your project and check its reference viewer. You'll almost certainly find at least one fat asset you can demote to soft.

Next week we'll look at async loading patterns in detail — how to load while showing a loading spinner, how to load in parallel, and how to avoid the classic "Async Load Asset in Tick" disaster.

— Marco