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.
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!