Visualizer Components
Source: Dev.to
Creating an Editor Module
To create an editor module, add a new folder whose name matches your runtime module with the suffix Ed or Editor (e.g., MyRuntime → MyRuntimeEditor).
The folder should contain the following files:
\Private\CustomModuleEd.cpp
\Public\CustomModuleEd.h
CustomModuleEd.Build.cs
CustomModuleEd.Build.cs
using UnrealBuildTool;
public class CustomModuleEd : ModuleRules
{
public CustomModuleEd(ReadOnlyTargetRules Target) : base(Target)
{
PrivateDependencyModuleNames.AddRange(new string[]
{
"Core",
"CoreUObject",
"Engine",
"Slate",
"SlateCore",
"UnrealEd",
"ComponentVisualizers"
});
}
}
CustomModuleEd.h
#pragma once
#include "Modules/ModuleInterface.h"
#include "Modules/ModuleManager.h"
class FCustomModuleEd : public IModuleInterface
{
public:
virtual void StartupModule() override;
virtual void ShutdownModule() override;
};
CustomModuleEd.cpp
#include "CustomModuleEd.h"
#include "UnrealEdGlobals.h"
#include "Editor/UnrealEdEngine.h"
IMPLEMENT_GAME_MODULE(FCustomModuleEd, CustomModuleEd);
void FCustomModuleEd::StartupModule() {}
void FCustomModuleEd::ShutdownModule() {}
Adding the Editor Module to Your Plugin
Edit the plugin’s .uplugin file and add the new module:
{
"FileVersion": 3,
...
"Modules": [
{
"Name": "CustomPlugin",
"Type": "Runtime",
"LoadingPhase": "Default"
},
{
"Name": "CustomModuleEd",
"Type": "Editor",
"LoadingPhase": "PostEngineInit"
}
]
}
Note: Set the loading phase to
PostEngineInit. You can verify that the module is loaded via Tools → Debug → Modules in the editor.
Adding a Debugger Component (Runtime)
Create a dummy component in your runtime module that will act as an intermediary between the editor visualizer and the data you want to display.
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;
/** Maximum distance at which debug geometry is drawn */
UPROPERTY(EditAnywhere, Category = "Debug")
float DrawDistance = 1000.0f;
/** Toggle drawing of debug points */
UPROPERTY(EditAnywhere, Category = "Debug")
bool ShouldDrawDebugPoints = false;
};
This component can expose additional properties or read data from its owning actor. It will be attached to any actor you wish to visualize.
Adding a Visualizer Component (Editor)
Create a new class inside the editor module that inherits from FComponentVisualizer. This class does not need an API macro because it is not exposed to other modules.
/**
* Visualizer for UDebuggerComponent.
* No API macro – we keep it editor‑only.
*/
class TestVisualizer : public FComponentVisualizer
{
public:
/** Draws the debug visualization */
virtual void DrawVisualization(const UActorComponent* Component,
const FSceneView* View,
FPrimitiveDrawInterface* PDI) override;
protected:
/** Cached reference to the actor owning the component */
AActor* ActorRef;
private:
FVector PreviousCameraLocation;
};
Implementation
void TestVisualizer::DrawVisualization(const UActorComponent* Component,
const FSceneView* View,
FPrimitiveDrawInterface* PDI)
{
const UDebuggerComponent* DebuggerComp = Cast(Component);
if (!DebuggerComp || !DebuggerComp->ShouldDrawDebugPoints)
{
return;
}
// Example: draw a green point at the actor’s location
PDI->DrawPoint(ActorRef->GetActorLocation(),
FLinearColor::Green,
25.0f,
SDPG_Foreground);
}
Tip: Attach
UDebuggerComponentto any actor you want to debug, either via Blueprint, in the level, or programmatically usingCreateDefaultSubobjectin the actor’s constructor.
Registering the Visualizer (Editor Startup)
Finally, register the visualizer in the editor module’s StartupModule and clean it up in ShutdownModule.
void FCustomModuleEd::StartupModule()
{
if (GUnrealEd)
{
// Create and register the visualizer
TSharedPtr<TestVisualizer> TestViz = MakeShareable(new TestVisualizer());
GUnrealEd->RegisterComponentVisualizer(
UDebuggerComponent::StaticClass()->GetFName(),
TestViz);
// Notify the visualizer that it has been registered
TestViz->OnRegister();
}
}
void FCustomModuleEd::ShutdownModule()
{
if (GUnrealEd)
{
// Unregister the visualizer when the module shuts down
GUnrealEd->UnregisterComponentVisualizer(
UDebuggerComponent::StaticClass()->GetFName());
}
}
Now, when you open the editor and select an actor that contains UDebuggerComponent, the TestVisualizer will draw the debug points according to the component’s settings.
Here is the same content, tidied up while preserving the original structure and meaning.
// Example snippet (C++)
gerComponent::StaticClass()->GetFName());
}
}
Enter fullscreen mode
Exit fullscreen mode
Now compile and launch the editor. When you select the actor that has the debugger component attached, the PDI will draw the debug visuals you mentioned in the DrawVisualization function inside the class.