Programming Design And Type Casting Cost

I see a lot of type casting to detect custom Actor types in examples. Detecting if the custom type is an A type then…if is a B type then… Is using Cast fast enough to detec bunch of types. Of course it must be used when need to use type’s specific method or member but in most cases an enumeration can handle most cases faster then type casting.

Lets consider the situation below.

class AAnimal : public AActor;
class AWildAnimal: public AAnimal;
class APrettyAnimal: public AAnimal;

When it is required to learn if the Actor is an Animal or not (when it is not necessary to learn is it Wild or Pretty) simply checking via type casting to AAnimal result should be fine. But when more detail required for the type of the Animal some enumeration can be faster. Because the cost of the first code is worse then the cost of the second code below.

First:

AWildAnimal *wild = Cast<AWildAnimal>();
if  (wild) { // ...}
APrettyAnimal *pretty = Cast<APrettyAnimal>();
if (pretty) { // ... }

Second:

AAnimal *animal = Cast<AAnimal>();
if (animal)
{
    switch (animal->Type)
    {
        case EAnimalType_Wild { // ... }
        case EAnimalType_Pretty { //... }
    }
}

In the second example, for more deeper inheritence levels, bit masking /enum flags makes it faster.

So here is my questions:

  1. Am I right?
  2. How does Unreal Reflection System work?
  3. Irrelevant question: I don’t really understand why am I using Characters instead of Pawns for AI?

Addressing two of these:

  1. The runtime cost might be higher for using casts, but the system is much more extensible. I don’t need to have switch statements all over the place which all have to be updated any time I need to include an updated type. Casting also automatically lets me see if the object in question is descended from the type I am trying to cast to (and therefore can take advantage of polymorphism), with a type enum this would require some additional logic that is maintained by you rather than being inherent to the language.
    Maintainability is one of the key indicators of code quality, IMO - if performance trumped usability in all things, we’d still be writing assembly.

  2. Characters are descended from Pawns, but have additional components such as a Movement Component already attached, saving you a few extra steps - they are essentially a Pawn ‘set up’ correctly for being able to path around, etc.

You helped a lot thanks. I just don’t know much about UE4’s Reflection System. If it costs less like static_cast then there is no problem.

Unreal RTTI is pretty simple - it’s single inheritance, for each UObject you define, a unique UClass object is generated (Unreal generates c++ stubs for these at pre-build step). It parses your UObject class definition, locates all UPROPERTY and UFUNCTION markers and generates UProperty and UFunction objects for these, inserts them into the generated unique UClass object. Records parenting information. There’s quite a bit of other magic on top (like CDOs etc). When you do cast, it just check’s your UObject’s instance’s UClass and then compares it against the UClass you’ve passed, walking down the chain if necessary. That’s it. Blueprint is basically more magic on top of this magic.

I spent a fair bit of time now hacking around Unreal RTTI limitations. My biggest beef is that RTTI is used extensively for UI generation in editor and is not designed to be extended in any way. So basically, if you need to generate your own class at runtime and insert some properties into it, you are in for a ride (same goes for patching existing classes).

In either case, regarding your question, yes, there’s an overhead cost. Also for casting there’s something called class cast flags, which are used to cast quickly between most common class types.

Good luck.