Creating a Point Light Component in Unreal Engine 5 with C++
Adding a point light component to an actor is fairly straight forward and can be pretty fun when we randomize the colors.
Software Versions: Unreal Engine 5.5.1 | Rider 2024.3.2
Project Name: MyProject
Create a new actor class, I called mine MyPointClass
. I added a forward reference at the top of file above the class declaration with class UPointLightComponent;
. Then inside the class I added a couple of simple properties to build out the actor. I also added a couple functions to have fun with the demo that will radomized the color when called.
MyPointLight.h
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "MyPointLight.generated.h"
class UPointLightComponent;
UCLASS()
class MYPROJECT_API AMyPointLight : public AActor
{
GENERATED_BODY()
public:
// Sets default values for this actor's properties
AMyPointLight();
UPROPERTY(EditAnywhere)
USceneComponent* MyRoot;
UPROPERTY(EditAnywhere)
UPointLightComponent* MyPointLight;
UPROPERTY()
FTimerHandle TimerHandle;
UFUNCTION()
void ToggleTimer();
void SetRandomColor();
};
First, inside the .cpp
file you'll need to include the point light component with #include "Components/PointLightComponent.h"
. Then inside the actor's constructor I chose some popular point light values to set at random. The ToggleTimer
function will be called from another actor on overlap to randomly set the point light's color every one to three seconds.
MyPointLight.cpp
#include "MyPointLight.h"
#include "Components/PointLightComponent.h"
// Sets default values
AMyPointLight::AMyPointLight()
{
MyRoot = CreateDefaultSubobject<USceneComponent>(TEXT("MyRoot"));
RootComponent = MyRoot;
MyPointLight = CreateDefaultSubobject<UPointLightComponent>(TEXT("MyPointLight"));
MyPointLight->SetLightColor(FColor::MakeRandomColor());
MyPointLight->SetIntensity(FMath::RandRange(5000.f, 10000.f));
MyPointLight->SetUseTemperature(FMath::RandBool());
MyPointLight->SetTemperature(FMath::RandRange(4000.f, 8000.f));
MyPointLight->SetAttenuationRadius(FMath::RandRange(1000.f, 2000.f));
MyPointLight->SetSourceRadius(FMath::RandRange(0.f, 100.f));
MyPointLight->SetupAttachment(RootComponent);
}
void AMyPointLight::ToggleTimer()
{
if (GetWorldTimerManager().IsTimerActive(TimerHandle))
{
GetWorldTimerManager().ClearTimer(TimerHandle);
}
else
{
GetWorldTimerManager().SetTimer(TimerHandle, this, &AMyPointLight::SetRandomColor, FMath::RandRange(1.f, 3.f), true, 0.f);
}
}
void AMyPointLight::SetRandomColor()
{
MyPointLight->SetLightColor(FColor::MakeRandomColor());
}
Next, solely for the GD Tactics Gym, I created a overlap trigger that on overlap loops through a TArray
of MyPointLights
to start each point light's timer function.
MyPointLightToggleTrigger.h
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "MyPointLightToggleTrigger.generated.h"
class AMyPointLight;
class UBoxComponent;
class UTextRenderComponent;
UCLASS()
class MYPROJECT_API AMyPointLightToggleTrigger : public AActor
{
GENERATED_BODY()
public:
// Sets default values for this actor's properties
AMyPointLightToggleTrigger();
UPROPERTY(EditAnywhere)
USceneComponent* MyRoot;
UPROPERTY(EditAnywhere)
UStaticMeshComponent* MyStaticMesh;
UPROPERTY(EditAnywhere)
UBoxComponent* MyBoxComponent;
UPROPERTY(EditAnywhere)
UTextRenderComponent* MyTextRenderComponent;
UPROPERTY(EditAnywhere, BlueprintReadWrite)
TArray<AMyPointLight*> MyPointLights;
UFUNCTION()
void OnBeginOverlap(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult);
};
MyPointLightToggleTrigger.cpp
#include "MyPointLightToggleTrigger.h"
#include "MyPointLight.h"
#include "Components/BoxComponent.h"
#include "Components/TextRenderComponent.h"
// Sets default values
AMyPointLightToggleTrigger::AMyPointLightToggleTrigger()
{
MyRoot = CreateDefaultSubobject<USceneComponent>(TEXT("MyRoot"));
MyRoot->bVisualizeComponent = true;
RootComponent = MyRoot;
MyStaticMesh = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("MyStaticMesh"));
MyStaticMesh->SetupAttachment(RootComponent);
MyTextRenderComponent = CreateDefaultSubobject<UTextRenderComponent>(TEXT("MyTextRenderComponent"));
MyTextRenderComponent->SetupAttachment(RootComponent);
MyBoxComponent = CreateDefaultSubobject<UBoxComponent>(TEXT("MyBoxComponent"));
MyBoxComponent->SetupAttachment(RootComponent);
MyBoxComponent->OnComponentBeginOverlap.AddDynamic(this, &AMyPointLightToggleTrigger::OnBeginOverlap);
}
void AMyPointLightToggleTrigger::OnBeginOverlap(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult)
{
if (OtherActor != nullptr && OtherActor != this)
{
for (AMyPointLight* MyPointLight : MyPointLights)
{
MyPointLight->ToggleTimer();
}
}
}
Finally, after compiling the project we can directly drag the C++ actors into our level and enjoy the lights we have created.
I had fun making this, hopefully this helps you in your game dev journey.
Harrison McGuire