Unreal Outlines & Implementation
Table of Contents
Introduction
In this post I will be looking at implementing outlines in Unreal Engine 5 using post processing materials, and then will implement them into my interaction system via C++ interfaces.
This post is a continuation of my previous post on creating pickupable items in Unreal Engine 5 with C++, and is part of my series of documenting what I learn while creating a hotdog truck simulator game in Unreal Engine 5.
Creating the outline post processing material
To create the outline effect, I will be using a material that can be applied via a post processing volume. Start in the material editor by creating a new material, ensuring the domain is set to Post Process.

To remove any jittering in the outline effect, find the Blendable Location option in the material details panel, and set it to Scene Color After DOF. 
Setting up the post process volume
The process volume must affect the whole level. This can be done by first adding a post process volume to the level, and checking the Unbound option in the details pane. 
The outline material has to then be added to the post process materials array in the details panel of the post process volume. 
Showing and hiding outlines
To show and hide outlines on objects, we can make use of the render custom depth pass property on mesh components.
When an object has the render custom depth pass enabled, it will be rendered to a separate buffer that the post process material can access to create the outline effect.
Testing this out by finding a mesh in the level and enabling the Render Custom Depth Pass option in the details panel will show if the outline effect is working. 
This will immediately show the outline on the object in the level. 
Creating an outline component in C++
To make it easier to show and hide outlines on any object, I will be making an actor component that can be added to any actor and will handle enabling and disabling the outline effect via an interface.
Before making the component, I will first create an interface to handle the outline functions.
class FASTFOODGAME_API IOutlineUtilities
{
GENERATED_BODY()
// Add interface functions to this class. This is the class that will be inherited to implement this interface.
public:
virtual void ShowOutline() = 0;
virtual void HideOutline() = 0;
};With the interface created and the methods to hide and show the outline defined, I can make the outline component.
In this component, we make sure to inherit from the interface we just created.
class FASTFOODGAME_API UOutlineComponent : public UActorComponent, public IOutlineUtilitiesWe can then override the ShowOutline and HideOutline methods. I also create a private property to hold a reference to the static meshes on the owner actor, so that we are not constantly trying to retrieve them every time we want to show or hide the outline.
private:
UPROPERTY()
TArray<UStaticMeshComponent*> OwnerStaticMeshes;
public:
// Outline interface
virtual void HideOutline() override;
virtual void ShowOutline() override;In the BeginPlay method of the outline component, the static meshes can be retrieved and stored.
void UOutlineComponent::BeginPlay()
{
Super::BeginPlay();
// Cache the owner's static meshes
AActor* owner = GetOwner();
owner->GetComponents<UStaticMeshComponent>(OwnerStaticMeshes);
}Finally, the override implementations for showing and hiding the outline can be provided.
void UOutlineComponent::HideOutline()
{
for (UStaticMeshComponent* mesh : OwnerStaticMeshes)
{
mesh->SetRenderCustomDepth(false);
}
}
void UOutlineComponent::ShowOutline()
{
for (UStaticMeshComponent* mesh : OwnerStaticMeshes)
{
mesh->SetRenderCustomDepth(true);
}
}Using the outline component on interactable actors
The outline component can now be added to any actor that we want to able to display outlines. I add it to the base interactable item class as part of the constructor.
AInteractableItem::AInteractableItem()
{
// Set this actor to call Tick() every frame. You can turn this off to improve performance if you don't need it.
PrimaryActorTick.bCanEverTick = true;
OutlineComponent = CreateDefaultSubobject<UOutlineComponent>(TEXT("OutlineComponent"));
}Using the outline from the interaction component
With the outline component added to the interactable item class, it can now be used in the interaction component when the player looks at an interactable object.
I'm not going to walk through the implementation of this, but I will provide the theory behind my approach.
When the player looks at an interactable object, I want to show the outline on that object. When the player looks away, I want to hide the outline.
To achieve this, I fire a linetrace on a very short interval (something like 0.05 seconds will suffice) to check what the player is looking at. If the player is looking at an interactable object, I can communicate to the outline component on that object to show the outline and store it as the previously highlighted actor. If the player is looking at something that is not interactable, I can communicate to the outline component on the previously highlighted actor to hide the outline, and clear the reference to the previously highlighted actor.
Keeping Everything Anonymous
To keep the interaction system decoupled from specific actor classes, I communicate with interactable items through an interface dedicated to interactable utilities. This allows access to a method to return the item's outline component as a generic UActorComponent*, without the interaction system needing to know the specific class type of the outline component.
The interaction component then communicates to that actor component to show and hide the outline using the outline utilities interface. This keeps both systems loosely coupled as there are no hard references and no direct class dependencies created through casting.
Taking this further
The outline effect can be further customised visually by modifying the material.
As for the logic, more complexity can be added to, for example, only show the outline on interactable items when the player is not holding an item, or generalising the PickupItem class from the previous post to be a more general InteractableItem class that allows for more interaction types beyond just picking up items.
Maybe the player can interact with things while holding an item, but not be able to pick up new items until they put down what they are holding.
My Reflection
Creating this outline system taught me a lot about optimisation strategies and good communication practices between different systems in Unreal Engine with C++.
- Using a component to hold the outline logic keeps code clean and manageable, and allows for reusability across any actor.
- Caching the mesh components right away avoids repeated lookups of the meshes every time the outline should be shown or hidden.
- Communicating exclusively through interfaces keeps systems decoupled and flexible, allowing for easier maintenance and future changes.