[Solved] How to typecast TSubclassOf<>?

I have a pickup class that has the following property, dictating what item it contains.

	UPROPERTY(EditDefaultsOnly, Category=Pickup)
	TSubclassOf<class AShooterItem> Item;

Now I need to cast Item to TSubclassOf~AShooterWeapon~ (AShooterWeapon extends AShooterItem in my project). How?

The obvious solution didn’t work:

TSubclassOf<AShooterWeapon> Weapon = Cast<TSubclassOf<AShooterWeapon> >(Item);

By the way, is there a difference between TSubclassOf~class Someclass~ and TSubclassOf~Someclass~?

PS: the site doesn’t supports (greater than) and (smaller than) symbols in text, I replaced them with ~.

TSubclassOf Weapon = Cast<TSubclassOf >(Item);

Can you do this?

TSubclassOf<AShooterWeapon> Weapon = Cast<AShooterWeapon>(Item);

"By the way, is there a difference between TSubclassOf and TSubclassOf"

What?

oh yes I see your comment now

the solution is to put it in code first, before you save it :slight_smile:

To answer the question, I’ve not experienced any functional difference in including the word class or excluding it, after many months of coding.


I’m not sure if you can cast on TSubclassOf, as class is not an object.
I think you would need first to spawn actor from that class and then cast it to whatever.

ActorSpawnParameters SpawnInfo;
		SpawnInfo.bNoCollisionFail = true;
		AShooterWeapon* itemBase = GetWorld()->SpawnActor<AShooterWeapon>(Weapon, SpawnInfo);

Rama, that didn’t work:

error C2440: 'initializing' : cannot convert from 'AShooterWeapon *' to 'TSubclassOf<TClass>'

iniside, I’ll wait and see if anyone has another idea.

You can’t cast classes to other classes. Class is just “blueprint” for object that will be created. You can cast objects to other objects that are in the same hierarchy. Could you explain what exactly are you trying to achieve ?

You can spawn class to actor like this:

ActorSpawnParameters SpawnInfo;
       SpawnInfo.bNoCollisionFail = true;
       AShooterWeapon* weaponBase = GetWorld()->SpawnActor<AShooterWeapon>(Weapon, SpawnInfo);

And then you can cast weaponBase to something else.

Oh, ok.

I wanted to cast it to TSubclassOf because another function takes a TSubclassOf as a parameter.

But doing so apparently worked:

AShooterWeapon* Weapon = Cast<AShooterWeapon>(Item);
// ...
TestPawn->FindWeapon( Weapon->GetClass() )

Thanks for the help! :slight_smile:

Hi Guys,

Do you want “Item” to represent an instance of some item (an actual item object that has already been created)? Or do you want it to be a type of object (to maybe spawn at a later time or something)?

If you want it to point to an actual item, then you probably want to use TSubobjectPtr instead of TSubclassOf, like so:

UPROPERTY(EditDefaultsOnly, Category=Pickup)
TSubobjectPtr<class AShooterItem> Item;

From there, you can easily cast it like this:

AShooterWeapon* Weapon = Cast<AShooterWeapon>(Item);

If instead you did want “Item” to be a type (an item class), you can check if that class is a AShooterWeapon or not with this:

Item->IsChildOf(AShooterWeapon::StaticClass());

Lastly, the “class” prefix before “SomeClass” is a C++ syntax feature. You are forward declaring that class. The header file that you are in doesn’t know what “SomeClass” is. Because the file doesn’t use the nitty-gritty insides of SomeClass, you can just “forward declare” it and let the file know just what type it is. For more information, here’s a wikipedia article: Forward declaration - Wikipedia

Actually,

AShooterWeapon* Weapon = Cast<AShooterWeapon>(Item);

always returns NULL, even when Item is subclass of AShooterWeapon.

Oh my I didnt even see that original definition.

Mike is right!

this is not what you want:

UPROPERTY(EditDefaultsOnly, Category=Pickup)
    TSubclassOf<class AShooterItem> Item

you want something like this

//non specific item instance
UPROPERTY(EditDefaultsOnly, Category=Pickup)
AShooterItem* Item;

//specific subclass
UPROPERTY(EditDefaultsOnly, Category=Pickup)
AMyFancyShooterItem* FancyItem;

#Now You can Cast

Now you can cast the non-specific Item to a specific sublcass

FancyItem = Cast<AMyFancyShooterItem>(Item);

I want it to be a type of object.

Item->IsChildOf(AShooterWeapon::StaticClass()) works for verifying the class.

But I have some functions that take a TSubclassOf~AShooterWeapon~ as parameter. For example:

bool CanPickupAmmo(TSubclassOf<AShooterWeapon> WeaponClass);

How could I pass the variable Item (which is a TSubclassOf~class AShooterItem~ Item;) to that function? Is spawning the only way?

That’s because Item is a class and not an instance of AShooterWeapon. See my answer below for full details, but I think you want to use TSubobjectPtr instead of TSubclassOf.

Or you can always spawn Item before trying to cast it.

I don’t know details but TSubclassOf should be usually used when you trying to get some data from Blueprint.

What makes you say this? Can you provide an example of what you mean?

I believe TSubclassOf is indeed what I want.

Using TSubobjectPtr returned an error saying it can’t be editable (I want it to be).

I want to be able to pick the item’s class in the pickup’s Blueprint defaults (the dropdown menu).

Edit: I tried using a simple pointer, but that wouldn’t let me pick the item’s class in blueprint.

Just to make it clear, the item in question may or may not be spawned during gameplay.

Ahh yes, that’s exactly what I needed.

Sorry if I wasn’t clear in the first place.

Thanks Mike and others!

void URPGEffectBPLibrary::ApplyEffect(ARPGCharacter* effectTarget, ARPGCharacter* causedBy, TSubclassOf appiledEffect)

This function is used to apply persistent effects to actors (like damage over time etc). Effects are implemented as Blueprints. I assumed that each effect can have unique gameplay mechanics, and didn’t wanted to code everything in C++.

I of course could pass effect as object to function, but I found it wasn’t really that clean and could generate confusion, for someone who doesn’t know, why object should be created before passing.

Got ya! Yeah, it looks like you do want TSubclassOf (sorry I didn’t fully understand what you were trying to do before). Here, let me suggest trying this:

if (Item->IsChildOf(AShooterWeapon::StaticClass()))
{
	TSubclassOf<AShooterWeapon> WeaponClass = *Item;
	CanPickupAmmo(WeaponClass);
}

Hopefully this helps! - Mike (Epic Games)

1 Like