Download

Return ENUM Variable value from function for comparison?

Hitting a breakpoint with the following function system, I’m trying to return a protected variable of type ‘enum’ via a public function, and then do a comparison to see if it equals another enum. How can I make the following code work properly?

BZGame_Weapon.h



	UFUNCTION(BlueprintPure, Category = "Weapon")
	EBZGame_WeaponClass GetWeaponClass() const;
	
protected:
	/* Weapon Class - Set By Code Automatically. */
	UPROPERTY(VisibleDefaultsOnly, Category = "Weapon")
	EBZGame_WeaponClass WeaponClass;


BZGame_Weapon.cpp



ABZGame_Weapon::ABZGame_Weapon(const FObjectInitializer& ObjectInitializer)
	: Super(ObjectInitializer)
{
	WeaponClass = EBZGame_WeaponClass::EWC_None;
}

EBZGame_WeaponClass ABZGame_Weapon::GetWeaponClass() const
{
	return WeaponClass;
}


That sets the variable of this specific class, but I want to see if the variable matches another one in the following class, to see if I can spawn it like so:

BZGame_GameObjectComponent.cpp



ABZGame_Weapon* TestWeapon = Cast<ABZGame_Weapon>(HardPoints*.DefaultWeapon);
if (TestWeapon->GetWeaponClass() == HardPoints*.HardpointClass)
{
          //Do Stuff


Hmm, checking enums with == is valid syntax, so something else must be causing your break.

maybe HardPoints* is a pointer?

I’m thinking it’s something to do with the way I’ve declared the enum… possibly. Am I declaring it the wrong way?

BZGame_Types.h



/* Enumerated Type For Powerup Class */
UENUM()
enum class EBZGame_WeaponClass : uint8
{
	EWC_None			UMETA(DisplayName = "None"),
	EWC_Cannon			UMETA(DisplayName = "Cannon"),
	EWC_Gun				UMETA(DisplayName = "Gun"),
	EWC_Rocket			UMETA(DisplayName = "Rocket"),
	EWC_Mortar			UMETA(DisplayName = "Mortar"),
	EWC_Special			UMETA(DisplayName = "Special"),
	EWC_Shield			UMETA(DisplayName = "Shield"),
	EWC_Max				UMETA(DisplayName = "Max")
};


nothing wrong ,can you tell exactly where you get a breakpoint

Yeah sure, I get it here initlaiital, on ‘return WeaponClass’

EBZGame_WeaponClass ABZGame_Weapon::GetWeaponClass() const
{
return WeaponClass;
}

the error isn’t coming from there , check this


ABZGame_Weapon* TestWeapon = Cast<ABZGame_Weapon>(HardPoints*.DefaultWeapon);

if(Weapon != nullprt)
{
if (TestWeapon->GetWeaponClass() == HardPoints*.HardpointClass)
{
///
}
}
else
{
 GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, TEXT("this pointer is null"));
}

Not sure if this is related, I’m getting a similar error here… perhaps casting to the value of a struct isn’t such a good idea? The following code never prints out the message, indicating that the cast is failing…



ABZGame_Ordnance* OrdCheck = Cast<ABZGame_Ordnance>(WeaponConfig.OrdnanceClass);
if (OrdCheck)
{
	GEngine->AddOnScreenDebugMessage(-1, 5.0f, FColor::Red, FString::Printf(TEXT("ORD CHECK")));
}


Tried the code you posted, and also checked with == nullptr. With the == null ptr it proceeded through, so the cast is definitely failing. This must be something to do with having a struct with a <TSubclassof> system in there maybe.

https://answers.unrealengine.com/questions/32654/blueprint-cast-support-for-ustructs.html

If you’re worried about the cast failing because WeaponConfig is a struct, don’t be because that doesn’t matter. You already mentioned that in both cases the cast returns null pointers, so the casts are failing. Are you sure you initialized the values you’re attempting to cast? Use an F9 breakpoint right after casting to check the values of your input. For example to check whether WeaponConfig.OrdnanceClass is initialized.

Yea the values are initialized and do exist. Oddly enough I did exactly what you said for a similar issue using TSubclassOf, where the cast couldn’t actually access the discrete class specified there (and so was failing, which was why I kept getting an AV crash).

I did a bit more digging and found that when I was using a TSubclassOf<Blah> inside a USTRUCT, I couldn’t call functions on that Subclass. It makes sense (but for reasons I can’t currently remember), and I’m wondering if the same thing applies to Enums?

To get around the TSubclassOf problem, I have to return the default class of that variable like this (From Answerhub Post Here):



WeaponConfig.OrdnanceClass->GetDefaultObject<ABZGame_Ordnance>()->GetAmmoCost();


The GetDefaultObject function seems to just be a slightly slower but safe cast, and allows me to actually call functions on that object and in this case, return a variable from it. Beforehand, this wouldn’t work and gave me an access violation (same error and in the same location as the enum issue). I’m wondering if there’s a similar function to ‘GetDefaultObject()’ for enums, or if I can use that same function on an enum declared like so (I think, if I remember the syntax properly):



enum class EBZGame_WeaponClass
{
       Type:
       Blah
       Blah
};


Hey try it like this.

/* Enumerated Type For Powerup Class */


UENUM()
namespace EBZGame_WeaponClass
{
	enum Type {
		EWC_None			UMETA(DisplayName = "None"),
		EWC_Cannon			UMETA(DisplayName = "Cannon"),
		EWC_Gun				UMETA(DisplayName = "Gun"),
		EWC_Rocket			UMETA(DisplayName = "Rocket"),
		EWC_Mortar			UMETA(DisplayName = "Mortar"),
		EWC_Special			UMETA(DisplayName = "Special"),
		EWC_Shield			UMETA(DisplayName = "Shield"),
		EWC_Max				UMETA(DisplayName = "Max")
	};
}

Here is how you could return a enum.


TEnumAsByte<EBZGame_WeaponClass::Type> YourEnum;
TEnumAsByte<EBZGame_WeaponClass::Type> GetEnumType()
{
      return YourEnum;
}

Hope it helps. :slight_smile:
WCode

Didn’t work WCode, I get a breakpoint on the last function you wrote in that text. This function is the cause of the breakpoint, but the breakpoint appears in the actual ‘GetWeaponClass’ function.



void UBZGame_GameObjectComponent::SpawnDefaultHardpoints()
{
	if (GetOwner()->Role < ROLE_Authority)
	{
		return;
	}

	int32 NumWeaponClasses = HardPoints.Num();
	for (int32 i = 0; i < NumWeaponClasses; i++)
	{
		if (HardPoints*.DefaultWeapon)
		{
			ABZGame_Weapon* TestWeapon = Cast<ABZGame_Weapon>(HardPoints*.DefaultWeapon);
			if (TestWeapon->GetWeaponClass() == HardPoints*.HardpointClass)
			{
				FActorSpawnParameters SpawnInfo;
				SpawnInfo.bNoCollisionFail = true;
				ABZGame_Weapon* NewWeapon = GetWorld()->SpawnActor<ABZGame_Weapon>(HardPoints*.DefaultWeapon, SpawnInfo);
				AddWeapon(NewWeapon, i);
			}
			else
			{
				GEngine->AddOnScreenDebugMessage(-1, 5.0f, FColor::Red, FString::Printf(TEXT("Weapon Class in Hardpoint %i Doesn't Match Hardpoint Class!"), i));
			}
		}
	}
}


Not sure whats wrong but the code above should work.
I use the same stuff in my own project versions 4.3 - 4.6.1.

Fixed! Had to do the same thing here using the GetDefaultObject function.



void UBZGame_GameObjectComponent::SpawnDefaultHardpoints()
{
	if (GetOwner()->Role < ROLE_Authority)
	{
		return;
	}

	int32 NumWeaponClasses = HardPoints.Num();
	for (int32 i = 0; i < NumWeaponClasses; i++)
	{
		if (HardPoints*.DefaultWeapon)
		{
			TEnumAsByte<EBZGame_WeaponClass::Type> TestWeapon = HardPoints*.DefaultWeapon->GetDefaultObject<ABZGame_Weapon>()->GetWeaponClass();
			if (TestWeapon == HardPoints*.HardpointClass)
			{
				FActorSpawnParameters SpawnInfo;
				SpawnInfo.bNoCollisionFail = true;
				ABZGame_Weapon* NewWeapon = GetWorld()->SpawnActor<ABZGame_Weapon>(HardPoints*.DefaultWeapon, SpawnInfo);
				AddWeapon(NewWeapon, i);
			}
			else
			{
				GEngine->AddOnScreenDebugMessage(-1, 5.0f, FColor::Red, FString::Printf(TEXT("Weapon Class in Hardpoint %i Doesn't Match Hardpoint Class!"), i));
			}
		}
	}
}


Great :slight_smile: glad you got it working.