none
Nasal demons

Unreal Engine 4 makes use of C++ instead of some other high level programming / scripting language. C++ offers a lot more power and control, but with greater power comes also greater chances that demons may fly out of your nose, as you'll read in this post. It all started with the implementation of the stealing functionality, as is present in the current version of Supraball in UE3. Stealing the ball worked fine, except under some circumstances the game would just crash, thanks to some assertion error. Now because of my shitty PC and the need for a lightweight IDE, I usually program in just a text editor and compile Supraball in what is called "Development" mode. However, after an hour I could not figure out the problem and decided I need to get the debugger out.

I started up Visual Studio and selected "DebugGame" mode, instead of "Development", so that I could put so called breakpoints in the code and examine the problem more closely. However, before I got the chance to actually debug, I noticed that the weapon was nowhere to be seen. I'm sure the weapon was working fine before, so I went back to "Development" mode, and lo and behold, it was working fine. I did project clean and full-rebuild back into "DebugGame" mode and the weapon was gone again. I did not have any debug-specific code, so what the hell was going on?

It turned out, the weapon was there. However, it was at the edge of the world. And I could not change this location for some reason. So, in development mode everything was working fine:



However, in "DebugMode" I would get this:



All other actors and meshes would render fine, yet this bugger would vanish into the void for unknown reasons. Somebody suggested me to put a breakpoint in the weapon's constructor and watch the location variable as I stepped through the game. The place where it all went wrong was inside this function:

void AWeapon::OnConstruction(const FTransform& Transform)
{
    Super::OnConstruction(Transform);

    // Add additional 1st person model offsets.
    GetMesh1P()->AddLocalOffset(
        FVector(
            0,
            this->Settings.OffsetForward,
            this->Settings.OffsetUpward
        )
    );
}

We add a local offset to the weapon model, such that it looks nicely from first person perspective. The problem lay in the fact that that both this->Settings.OffsetForward and this->Settings.OffsetUpward were some weird numbers like 0xcccccc or MIN_INT. From previous experience, I had the feeling this would be because of these variables being uninitialized. And I was right. For the weapon, we have the following (shortened) settings structure:

/**
 * Settings data structure related to various general weapon settings.
 */
USTRUCT()
struct FWeaponSettings
{
    GENERATED_USTRUCT_BODY()

public:
    /**
     * Constructor.
     */
    FWeaponSettings();

    /**
     * Additional forward offset.
     * This moves the first person model in addition to default location.
     */
    UPROPERTY(EditAnywhere, Category = "Mesh")
    float OffsetForward;

    /**
     * Additional upward offset.
     * This moves the first person model in addition to default location.
     */
    UPROPERTY(EditAnywhere, Category = "Mesh")
    float OffsetUpward;
};

However, in the constructor we only have:

FWeaponSettings::FWeaponSettings()
{
    // Default kickrate as copied from UDK. This is for normal users.
    SetFireRate(0.9);
}


Therefore, we had only declared these variables, but we have not initialized them. In C++ this leads to undefined behaviour, as integer numbers, or even floats are not guarenteed to have a value equal to zero. For 8 months and being in "Development" mode, this was zero. Now, in "DebugMode", this value was not, and was probably the value of some leftover memory from maybe an other application. All I had to do was set this value to zero in the constructor, and all was fixed. Now I could finally start debugging the bug that I was actually supposed to fix!

It surprised me though, that the C++ compiler did not warn me. I was sure that with previous projects with GCC/Clang, the compiler would warn me about uninitialized variables if you'd turn on the -Wall compiler argument. Epic Games made their own build system, called Unreal Build Tool (UBT). I looked for Wall in the engine's source code on GitHub, and found out that the -Wall -Werror compiler arguments were only set in the Linux and Mac toolchain. Not in Windows, for whatever reason. Not even /WX. They only use /analyze, but then disable warnings as error messages with /analyze:WX-. I have no idea why Epic would do this, but it would save me a lot of time and bugs if they actually enabled the warnings as errors on Windows as well.

PS: http://catb.org/jargon/html/N/nasal-demons.html