Access Functions & Variables From a TSubclassOf Variable in C++

In this tutorial you will be shown how to access the variables and functions of a specific class that you have specified, inside a container.

Updated over 1 year ago Edit Page Revisions

Overview

Why

TSubclassOf is a special template of UClass which only accepts specific subclasses of some base class. So it's still a UClass which is just a class specifier which you can spawn things from, but it does not have the variables or functions of the declared class. However, you can call GetDefaultObject() which is a master copy of the defined class object and contains the default variables which you can use before spawning that object.

The Problem

In my example; I want to know how much ammunition a certain type of projectile will cost me in order to subtract it from my available ammunition, and to ensure I'm allowed to spawn it.

The Ordnance.h class allows me to return the (protected variable) cost of the ordnance object (usually a blueprinted Sub-class) using the float GetAmmoCost(); function:

Ordnance.cpp

float AOrdnance::GetAmmoCost()
{
    return AmmoCost;
}

If you have a specific actor of subclass, you can access this function without any issues. However, if you want to have a weapon that can specify any subclass of ordnance, you'll have to first get that specified class in order to call the function.

Example

The following code in Weapon.h declares a variable using the container. When blueprinted, it allows the developer to select a specific subclass of ordnance that we can fire from it. You'll also notice that this is part of a struct (this is not necessary, but for the purposes of the tutorial shows that the code works with UStructs):

Weapon.h

USTRUCT()
struct FWeaponData
{
    GENERATED_BODY()

    /* Actual Ordnance To Fire */
    UPROPERTY(EditDefaultsOnly, Category = "Ordnance")
    TSubclassOf OrdnanceClass;

    FWeaponData()
        : OrdnanceClass(NULL)
    {
    }
};

The following code in Weapon.cpp, allows me to access and cast to the specific class defined by that variable, and call functions on it. Traditionally you might think to try and perform a regular Cast, but doing so will result in a difficult-to-debug breakpoint, and stop your code from executing properly.

The key difference is the use of the GetDefaultObject() function provided by Unreal, which will actually perform a safe cast and a check to the specific subclass, enabling you to call functions on it and return values!

Weapon.cpp

void AWeapon::HandleFiring()
{
    /* Check if we have Enough Ammo To Fire */
    float OrdnanceCost = WeaponConfig.OrdnanceClass->GetDefaultObject()->GetAmmoCost();
    bool bEnoughAmmo = GetCurrentAmmo() >= OrdnanceCost;

    if (bEnoughAmmo)
    {
        FireWeapon(OrdnanceCost); // Tab-Out Pure-Virtual For Now!
    }
}

Note: You have to do this for ANY type of variable that you want to return from an object specified inside a variable!