Expert-Level Guide to Unreal Engine Slate UI & Custom Input Behaviors
Slate is Unreal Engineโs low-level UI framework, offering full control over UI elements and input handling. While UMG (Unreal Motion Graphics) is the easiest way to create UI, Slate is required for high-performance UI, editor tools, and custom UI behaviors.
๐น Part 1: Understanding Slate Fundamentals
๐ What is Slate?
Slate is Unrealโs immediate mode UI framework, meaning UI elements are redrawn every frame. Itโs lightweight and designed for real-time responsiveness, which is why itโs used extensively in editor tools and custom HUDs.
๐ Slate vs UMG โ Why Use Slate?
| Feature | Slate (C++) | UMG (Blueprint) | |โโโ|โโโโ|โโโโโ-| | Performance | โ Very Fast | โ Slower (Blueprint Overhead) | | Customization | โ Full Control | โ Limited to UMG Widgets | | Editor Tools | โ Used for Unreal Editor UI | โ Mostly for runtime UI | | Game UI | โ Advanced HUDs | โ Easy-to-use UI | | Input Handling | โ Custom Input Behaviors | โ Limited Input Customization |
๐ Use Slate when: You need maximum performance, complex custom UI, or need to modify input handling.
๐ How Slate Works (The Basics)
๐น Key Slate Concepts
| Concept | Description |
|โโโ|โโโโ|
| SWidget | Base class for all Slate UI elements. |
| SNew() | Macro for creating new Slate widgets. |
| Children | UI elements are nested inside containers (e.g., SVerticalBox
). |
| Arguments | UI elements take properties (.Text()
, .Padding()
, etc.). |
| Paint & Input Functions | Each widget paints itself and handles input events. |
๐น Part 2: Setting Up Slate in Your Project
1๏ธโฃ Include Slate Dependencies
In your projectโs Build.cs, add:
PublicDependencyModuleNames.AddRange(new string[] { "Slate", "SlateCore" });
Then include the Slate headers in your C++ file:
#include "SlateBasics.h"
#include "SlateExtras.h"
๐น Part 3: Creating a Basic Slate UI
Letโs create a simple UI with text and a button.
Step 1: Create a New Slate Widget Class
Create SMySlateWidget.h
:
#pragma once
#include "Widgets/SCompoundWidget.h" // Base class for custom widgets
#include "Widgets/Text/STextBlock.h"
#include "Widgets/Input/SButton.h"
class SMySlateWidget : public SCompoundWidget
{
public:
SLATE_BEGIN_ARGS(SMySlateWidget) {}
SLATE_ARGUMENT(FText, InitialText)
SLATE_END_ARGS()
void Construct(const FArguments& InArgs);
};
Step 2: Implement the Widget (SMySlateWidget.cpp
)
#include "SMySlateWidget.h"
void SMySlateWidget::Construct(const FArguments& InArgs)
{
ChildSlot
[
SNew(SVerticalBox)
+ SVerticalBox::Slot()
.AutoHeight()
[
SNew(STextBlock)
.Text(InArgs._InitialText) // Uses argument passed to the widget
]
+ SVerticalBox::Slot()
.AutoHeight()
[
SNew(SButton)
.Text(FText::FromString("Click Me!"))
.OnClicked_Lambda([]()
{
UE_LOG(LogTemp, Warning, TEXT("Button Clicked!"));
return FReply::Handled();
})
]
];
}
Step 3: Add the Widget to a Viewport
Inside a HUD class (AHUD
or AGameMode
), add:
TSharedPtr<SMySlateWidget> MySlateWidget;
void AMyHUD::BeginPlay()
{
Super::BeginPlay();
SAssignNew(MySlateWidget, SMySlateWidget)
.InitialText(FText::FromString("Hello, Slate!"));
GEngine->GameViewport->AddViewportWidgetContent(MySlateWidget.ToSharedRef());
}
โ Result: This will add a text block and button to the screen using Slate.
๐น Part 4: Creating Custom Slate Elements (Custom Input Behavior)
Now letโs create a custom input widget that listens for key presses and performs custom actions.
๐ Step 1: Define the Custom Widget Class
Create SMyCustomInputWidget.h
:
#pragma once
#include "Widgets/SCompoundWidget.h"
class SMyCustomInputWidget : public SCompoundWidget
{
public:
SLATE_BEGIN_ARGS(SMyCustomInputWidget) {}
SLATE_END_ARGS()
void Construct(const FArguments& InArgs);
virtual FReply OnKeyDown(const FGeometry& MyGeometry, const FKeyEvent& KeyEvent) override;
};
๐ Step 2: Implement the Input Handling
SMyCustomInputWidget.cpp
#include "SMyCustomInputWidget.h"
#include "SlateOptMacros.h"
#include "InputCoreTypes.h"
void SMyCustomInputWidget::Construct(const FArguments& InArgs)
{
ChildSlot
[
SNew(STextBlock)
.Text(FText::FromString("Press any key!"))
];
}
// Capture keyboard input
FReply SMyCustomInputWidget::OnKeyDown(const FGeometry& MyGeometry, const FKeyEvent& KeyEvent)
{
FKey PressedKey = KeyEvent.GetKey();
if (PressedKey == EKeys::SpaceBar)
{
UE_LOG(LogTemp, Warning, TEXT("Spacebar Pressed!"));
return FReply::Handled();
}
return FReply::Unhandled();
}
๐ Step 3: Add the Custom Input Widget to the Game
Inside your HUD or GameMode, add:
TSharedPtr<SMyCustomInputWidget> MyInputWidget;
void AMyHUD::BeginPlay()
{
Super::BeginPlay();
SAssignNew(MyInputWidget, SMyCustomInputWidget);
GEngine->GameViewport->AddViewportWidgetContent(MyInputWidget.ToSharedRef());
}
โ Result: The UI listens for keyboard input and logs โSpacebar Pressed!โ when the spacebar is hit.
๐น Part 5: Advanced Slate Input Handling (Mouse, Keyboard, Focus, Events)
You can override different input events to handle custom interactions.
Event | Description |
---|---|
OnMouseButtonDown() |
Detects mouse button presses. |
OnMouseMove() |
Tracks cursor movement. |
OnKeyDown() |
Handles key presses. |
OnKeyUp() |
Detects key releases. |
OnFocusReceived() |
Called when the widget gets focus. |
Example: Handling Mouse Clicks
FReply SMyCustomInputWidget::OnMouseButtonDown(const FGeometry& MyGeometry, const FPointerEvent& MouseEvent)
{
if (MouseEvent.GetEffectingButton() == EKeys::LeftMouseButton)
{
UE_LOG(LogTemp, Warning, TEXT("Left Mouse Clicked!"));
return FReply::Handled();
}
return FReply::Unhandled();
}
๐ฏ Conclusion
โ
Slate is a powerful C++ UI system for creating custom editor tools, HUDs, and advanced UIs.
โ
You can override input functions (OnKeyDown
, OnMouseButtonDown
) to create custom UI interactions.
โ
Slate is more performant than UMG but requires more code and setup.
๐ Next Steps:
Would you like a fully working project showcasing Slate UI, animations, and event-driven interactions? Let me know! ๐ฎ๐ฅ