Extending Gameplay Debugger

Gameplay Debugger I bet lots of you already are familiar with Unreals Gameplay Debugger. It’s a great tool that let us see very useful information in a convenient way. Whats cool about it is that i...

Updated 4 months ago Edit Page Revisions

Gameplay Debugger

I bet lots of you already are familiar with Unreals Gameplay Debugger. It’s a great tool that let us see very useful information in a convenient way. Whats cool about it is that it doesn’t just display text. It also show information about AI Perception and EQS visually making it super easy to debug. The best part is that it’s super easy to extend.

Base setup

Although extending Gameplay Debugger can be achieved within same module as your game I’d rather recommend doing it in a separate module hence link to the article about module creation here. All further steps assume you have separate module.

Creating new category

First of, add GameplayDebugger module to your ModuleName.Build.cs file under dependencies modules.

Now create custom class that will inherit from FGameplayDebuggerCategory. To stick with Unreals convention of already existing classes (like AI and BehaviorTree etc.) I’d suggest naming it FGameplayDebuggerCategory_CategoryName. I’ll use FGameplayDebuggerCategory_Generic name in this example.

// GameplayDebuggerCategory_Generic.h

#pragma once

#if WITH_GAMEPLAY_DEBUGGER

#include "CoreMinimal.h"
#include "GameplayDebuggerCategory.h"

class APlayerController;
class AActor;

class FGameplayDebuggerCategory_Generic : public FGameplayDebuggerCategory
{
public:
    FGameplayDebuggerCategory_Generic();
    void CollectData(APlayerController* OwnerPC, AActor* DebugActor) override;
    void DrawData(APlayerController* OwnerPC, FGameplayDebuggerCanvasContext& CanvasContext) override;
    
    static TSharedRef MakeInstance();
    
protected:
    struct FRepData
    {
        // Put all data you want to display here
        FString ActorName;
        
        void Serialize(FArchive& Ar);
    };
    
    FRepData DataPack;
};

#endif // WITH_GAMEPLAY_DEBUGGER
// GameplayDebuggerCategory_Generic.cpp

#include "GameplayDebuggerCategory_Generic.h"

#if WITH_GAMEPLAY_DEBUGGER

#include "GameFramework/Actor.h"
#include "GameFramework/PlayerController.h"

FGameplayDebuggerCategory_Generic::FGameplayDebuggerCategory_Generic()
{
    SetDataPackReplication(&DataPack);
}

void FGameplayDebuggerCategory_Generic::CollectData(APlayerController* OwnerPC, AActor* DebugActor)
{
    if (OwnerPC)
    {
        DataPack.ActorName = OwnerPC->GetPawn()->GetName();
    }
}

void FGameplayDebuggerCategory_Generic::DrawData(APlayerController* OwnerPC, FGameplayDebuggerCanvasContext& CanvasContext)
{
    if (!DataPack.ActorName.IsEmpty())
    {
        CanvasContext.Printf(TEXT("{yellow}Actor name: {white}%s"), *DataPack.ActorName);
    }
}

TSharedRef FGameplayDebuggerCategory_Generic::MakeInstance()
{
    return MakeShareable(new FGameplayDebuggerCategory_Generic());
}

void FGameplayDebuggerCategory_Generic::FRepData::Serialize(FArchive& Ar)
{
    Ar << ActorName;
}

#endif // WITH_GAMEPLAY_DEBUGGER

This simple template will display the name of debug actor under newly created category. Now we need to register new category inside our module startup function.

On top of your module source file include gameplay debugger and our new category:

#if WITH_GAMEPLAY_DEBUGGER
    #include "GameplayDebugger.h"
    #include "GameplayDebuggerCategory_Generic.h"
#endif // WITH_GAMEPLAY_DEBUGGER

Now in startup function register and name your new category:

/*...*/
void FYourNewModule::StartupModule()
{
#if WITH_GAMEPLAY_DEBUGGER
    IGameplayDebugger& GameplayDebuggerModule = IGameplayDebugger::Get();
    GameplayDebuggerModule.RegisterCategory("Generic", IGameplayDebugger::FOnGetCategory::CreateStatic(&FGameplayDebuggerCategory_Generic::MakeInstance), EGameplayDebuggerCategoryState::EnabledInGameAndSimulate, 1);
    GameplayDebuggerModule.NotifyCategoriesChanged();
#endif
}

/*...*/

And remove it on Shutdown


void FYourNewModule::ShutdownModule()
{
#if WITH_GAMEPLAY_DEBUGGER
	if (IGameplayDebugger::IsAvailable())
	{
		IGameplayDebugger& GameplayDebuggerModule = IGameplayDebugger::Get();
		GameplayDebuggerModule.UnregisterCategory("Generic");
		GameplayDebuggerModule.NotifyCategoriesChanged();
	}
#endif // WITH_GAMEPLAY_DEBUGGER

}
/*...*/

Result

Now regenerate project solution and you are ready to go. Launch the PIE and hit the ' (apostrophe) key to see your new category up and running.

File:Result.png

If you want to change binding key or default visibility of categories you can do so by opening Project Settings under the Gameplay Debugger tab. For more references how to draw your debug things you can take a look into GameplayDebuggerCategory_BehaviorTree or GameplayDebuggerCategory_EQS.