DEV Community

Cover image for Visualizer Components
Haris
Haris

Posted on

Visualizer Components

Visualizer components are editor only components which helps us draw non-rendering debug information to the screen or HUD, this is more like a modular, lightweight, debug component that does not get shipped with packaged game.

Creating An Editor Module

To Create an editor module, you need to create a new folder with same name as your runtime module but postfix it by “Ed” or “Editor” for example:
Have the following files inside your module folder:

\Private\CustomModuleEd.cpp
\Public\CustomModuleEd.h
CustomModuleEd.Build.cs
Enter fullscreen mode Exit fullscreen mode

In your build.cs file:

using UnrealBuildTool;

    public class CustomModuleEd : ModuleRules
    {
         public CustomModuleEd(ReadOnlyTargetRules Target) : base(Target)
         {
               PrivateDependencyModuleNames.AddRange(new string[] 
               {
                   "Core", 
                   "CoreUObject", 
                   "Engine", 
                   "Slate", 
                   "SlateCore", 
                   "UnrealEd", 
                   "ComponentVisualizers"
               });
         }
    }
Enter fullscreen mode Exit fullscreen mode

And here is how your editor module class should look like:

    #pragma once
    #include "Modules/ModuleInterface.h"
    #include "Modules/ModuleManager.h"

    class FCustomModuleEd: public IModuleInterface
    {
        public:
        virtual void StartupModule() override;
        virtual void ShutdownModule() override;
    };
Enter fullscreen mode Exit fullscreen mode
#include "CustomModuleEd.h"
#include "UnrealEdGlobals.h"
#include "Editor/UnrealEdEngine.h"

IMPLEMENT_GAME_MODULE(FCustomModuleEd, CustomModuleEd);

void FCustomModuleEd::StartupModule() {}
void FCustomModuleEd::ShutdownModule() {}
Enter fullscreen mode Exit fullscreen mode

Once everything is done you can now add your editor module into your plugin file:

{
    "FileVersion": 3,
    ....
    "Modules": [
        {
            "Name": "CustomPlugin",
            "Type": "Runtime",
            "LoadingPhase": "Default"
        },
        {
            "Name": "CustomModuleEd",
            "Type": "Editor",
            "LoadingPhase": "PostEngineInit"
        }
    ]
}
Enter fullscreen mode Exit fullscreen mode

Make sure to set the loading phase to PostEngineInit, in case you want to check if your module is active in editor, you can go here Tools → Debug → Modules

Adding Component

The way visualization components works is by having a class type usually that is an actor component present outside the editor module that is attached to the actual Actor present inside your levels.

Hence, we need to create a dummy component inside our Runtime module, we are going to call it debugger component:

UCLASS( ClassGroup=(Custom), meta=(BlueprintSpawnableComponent))
class MYPROJECT_API UDebuggerComponent : public UActorComponent
{
    GENERATED_BODY()

public: 
    // Sets default values for this component's properties
    UDebuggerComponent();

protected:
    // Called when the game starts
    virtual void BeginPlay() override;

public: 
    // Called every frame
    virtual void TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction) override;

public:
    UPROPERTY(EditAnywhere, Category = "Debug")
    float DrawDistance = 1000.0f;

    UPROPERTY(EditAnywhere, Category = "Debug")
    bool ShouldDrawDebugPoints = false;

};
Enter fullscreen mode Exit fullscreen mode

Here we can also add properties, or we can simply read the properties from owning actor, but this component will act as an intermediary between our editor module visualizer and the data (Cover point locations) which exists inside our run-time module.

Add Visualizer Component in Editor Module

Create a new empty class inside the editor module and call it VisualizerComponent this will inherit from FComponentVisualizer.

/**
 *  Remove the API part of class definition because we don't want to expose this to other modules
 */
class TestVisualizer : public FComponentVisualizer
{
public:
    virtual void DrawVisualization(const UActorComponent* Component, const FSceneView* View, FPrimitiveDrawInterface* PDI) override;

protected:
    AActor* ActorRef; // Reference for actor which needs to show this debug

private:
    FVector PerviousCameraLocation;
};
Enter fullscreen mode Exit fullscreen mode
void TestVisualizer::DrawVisualization(const UActorComponent* Component, const FSceneView* View, FPrimitiveDrawInterface* PDI)
{
    const UDebuggerComponent* debuggerComp = Cast<UDebuggerComponent>(Component);
    if (!debuggerComp || !debuggerComp->ShouldDrawDebugPoints) { return; }
        PDI->DrawPoint(ActorRef->GetActorLocation(), FLinearColor::Green, 25.0f, SDPG_Foreground);
}
Enter fullscreen mode Exit fullscreen mode

To make this all work, you need to have your run-time debugger component added onto the actor you wish to have debug visualizers for, you can either do it manually in blueprints, instances or via C++ in constructor using default sub object.

Register your Visualizer in Editor Startup

The final step is to register your visualizer component and bind it with the debugger component during the startup function of your editor module.

Go back to the CustomModuleEd.cpp and implement the following:

void FCustomModuleEd::StartupModule()
{
    if (GUnrealEd)
    {
        const TSharedPtr<TestVisualizer > TestViz = MakeShareable(new TestVisualizer ());
        GUnrealEd->RegisterComponentVisualizer(UDebuggerComponent::StaticClass()->GetFName(), TestViz);
        TestViz->OnRegister();
    }
}

void FCustomModuleEd::ShutdownModule()
{
    if (GUnrealEd)
    {
        GUnrealEd->UnregisterComponentVisualizer(UDebuggerComponent::StaticClass()->GetFName());
    }
}
Enter fullscreen mode Exit fullscreen mode

Now Compile and launch the editor, once you will select the actor which has the debugger component attached to it, the PDI will draw the debugs you mentioned in DrawVisualization function inside the class.

Top comments (0)