April 10, 2023

Understanding Hard References and Soft References in Unreal Engine

Introduction

In game development, it is common to come across scenarios where you need to reference an asset, object, or class.

When referencing an asset, you can either use a hard reference or a soft reference.

Understanding the difference between these two types of references is crucial for any game developer, especially those using Unreal Engine. In this article, we will discuss hard references and soft references and how to use them in Unreal Engine.

Hard References

Hard references are direct pointers to an asset or object that are set at compile-time. This means that if you delete the asset, object or class that a hard reference is pointing to, your code will no longer compile.

Hard references are generally faster to access than soft references since they don't require any extra lookups.

To create a hard reference in Unreal Engine, you simply declare a variable with the type of the asset, object or class you want to reference, and assign it to the specific asset or object. For example, if you want to reference a blueprint of a character in C++, you would declare a variable of the type AMyCharacter, where AMyCharacter is the class of your blueprint, and assign it to the specific blueprint.


#include "MyCharacter.h"

class AMyClass
{
public:
    AMyCharacter* MyCharacterRef = nullptr; // Declare a hard reference to MyCharacter blueprint
    ...
};

void AMyClass::MyFunction()
{
    MyCharacterRef = Cast(StaticLoadObject(AMyCharacter::StaticClass(), NULL, TEXT("/Game/MyContent/MyCharacter.MyCharacter"), NULL, LOAD_None, NULL)); // Assign the hard reference to the specific MyCharacter blueprint
    ...
}


Soft References

Soft references, on the other hand, are indirect pointers to an asset, object, or class that are set at runtime. This means that if you delete the asset, object or class that a soft reference is pointing to, your code will still compile. Soft references are generally slower to access than hard references since they require an extra lookup to find the asset, object or class at runtime.

To create a soft reference in Unreal Engine, you can use various classes that implement soft reference functionality, such as TSoftObjectPtr, TSoftClassPtr, and TSoftAssetPtr. These classes allow you to specify the path to the asset, object, or class that you want to reference at runtime, instead of hard-coding it in your code.


#include "SoftObjectPtr.h"
#include "MyCharacter.h"

class AMyClass
{
public:
    TSoftObjectPtr MyCharacterRef = nullptr; // Declare a soft reference to MyCharacter blueprint
    ...
};

void AMyClass::MyFunction()
{
    MyCharacterRef = TEXT("/Game/MyContent/MyCharacter.MyCharacter"); // Assign the soft reference to the specific MyCharacter blueprint
    ...
}

Which one to use?

Choosing between hard references and soft references depends on the specific use case. If you have an asset, object or class that is crucial to the functionality of your code, and you want to ensure that it always exists, then you should use a hard reference. If, on the other hand, you have an asset, object or class that is not crucial to the functionality of your code, and you want to allow it to be deleted or modified without breaking your code, then you should use a soft reference.

When to use hard references?

Hard references are best used when you know that a specific object will always exist and you want to ensure that it is always accessible. This is particularly useful when referencing core engine objects or when setting up initial references that are necessary for the proper functioning of your game or application.

For example, if you have a player character that always exists in your game, you might use a hard reference to ensure that other systems can always access it. Similarly, if you have a critical game asset that must always be available, you might use a hard reference to ensure that it is loaded and accessible at all times.

When to use soft references?

Soft references are best used when you want to allow an object to be loaded and unloaded dynamically, based on the needs of your game or application.

This is particularly useful for large game assets, such as maps or levels, which can take up a lot of memory and processing power.

For example, if you have a large open world game with many different levels, you might use soft references to load and unload individual levels as needed, rather than loading them all at once and taking up unnecessary memory. Similarly, if you have a game asset that is only used in certain situations, you might use a soft reference to load it only when it is needed and unload it when it is no longer necessary.

Pros and cons of hard references

One of the biggest advantages of hard references is that they provide a reliable way to ensure that an object is always accessible.

This can be critical for objects that are necessary for the proper functioning of your game or application.

However, hard references can also be inflexible, since they require that the referenced object always exists. This can be problematic if you need to change the object or its location, since it can break any references to it.

Pros and cons of soft references

The biggest advantage of soft references is that they provide a more flexible way to load and unload objects dynamically, based on the needs of your game or application.

This can be particularly useful for large game assets or for situations where objects are only used in certain situations.

However, soft references can also be less reliable, since they rely on the object being loaded and available when it is needed. This can lead to unexpected errors or performance issues if the object is not loaded in time.

Conclusion

In general, hard references are best used for objects that are critical to the functioning of your game or application and that you know will always exist.

Soft references are best used for objects that can be loaded and unloaded dynamically, based on the needs of your game or application.

It's important to choose the right type of reference for each situation, as using the wrong type of reference can lead to unexpected errors, performance issues, or other problems.

By understanding the strengths and weaknesses of each type of reference, you can make informed decisions about how to structure your code and manage your game assets.