Download

Questions about the coding style

I have a few questions about how I should approach problems. I usually would just solve them how I think they would be solved best but I think there is some value in approaching problems the same way that epic does.

1.) Casting everywhere, avoiding interfaces?

This code is from the SurvivalGame and it looks like


void ASConsumableActor::OnUsed(APawn* InstigatorPawn)
{
	// Plays pickup sound from base class
	Super::OnUsed(InstigatorPawn);

	ASCharacter* Pawn = Cast<ASCharacter>(InstigatorPawn);
	if (Pawn)
	{
		Pawn->ConsumeFood(Nutrition);
	}

	// Remove from level
	Destroy();
}

I don’t want to pick on this code but I saw this also several times in the gameplay framework myself. It seems UE is avoiding interfaces as much as possible and just does a simple cast like


ASCharacter* Pawn = Cast<ASCharacter>(InstigatorPawn);

Do you know why? Simplicity?

The problem I see with this code is that if I ever decide to create another playable character in the future I would have to change code in every ConsumeableAactor.

I probably would have written something like this


void ASConsumableActor::OnUsed(AActor* Instigator)
{
	// Plays pickup sound from base class
	Super::OnUsed(Instigator);

	IFood* Food= Cast<IFood>(Instigator);
	if (Food)
	{
		Food->ConsumeFood(Nutrition);
	}

	// Remove from level
	Destroy();
}

I also thought about using components which gives me the ability to add functionality at runtime, it also encapsulates the implementation and makes it reusable.

What would you recommend?

2.) NULL vs nullptr

I see code a lot that looks something like this


ASCharacter* MyPawn = PCOwner ? Cast<ASCharacter>(PCOwner->GetPawn()) : NULL;

But UE also uses nullptr in some places


template <typename From, typename To, ECastType CastType = TGetCastType<From, To>::Value>
struct TCastImpl
{
	// This is the cast flags implementation
	FORCEINLINE static To* DoCast( UObject* Src )
	{
		return Src->GetClass()->HasAnyCastFlag(TCastFlags<To>::Value) ? (To*)Src : nullptr;
	}
};

So I think Epic embraces nullptr over NULL now?
Update It seems it is already documented

3.) What is the meaning of ‘FFoo’?


Most other classes are prefixed by F, though some subsystems use other letters

Just out of curiosity, what does F stand for? Fixed?

On the interface topic, yes Interfaces need some TLC in UE4. People fear multiple inheritance like the Grim Reaper it seems but that fear is completely unnecessary if interfaces are used carefully. I think part of the issue with interfaces not being so widely used also has to do with limitations of the reflection system (i.e. IMyInterface::StaticClass() does not exist). With interfaces in UE4, the StaticClass is defined for the UInterface-derived portion of an interface’s definition which causes some major limitations. I had a discussion with someone about this and they suggested virtual inheritance as a preferred solution to what interfaces would normally achieve, although I haven’t started to use this myself yet (I’m from a c# background and it looked like voodoo to me lol).

I still use interfaces, and they can be used safely as long as you plan carefully where and why they get used. I most commonly use interfaces as a sort of way of “tagging” a type as supporting a group of functionality (i.e. ITargetable, IConsumable, etc). Checking to ensure a class inherits from an interface is easy enough and can be used as a “filter” of sorts on object searches. Some would argue there are other ways of doing this and they are absolutely right but interfaces do exist for a reason. Sometimes it is the best and least confusing way ensure completely unrelated objects share a common functionality.

As for the FFoo things, its just a naming convention. You can find more on this in the UE4 docs under coding standards but the jist is a type declared with an F infront of it generally means it is a class or struct that doesn’t fall under any of the other naming conventions (i.e. U - UObject derived, A - AActor-derived, etc.).