2 min read

[5/50] Dynamic sunlight and environment changes with C++ in Unreal Engine

An anime style image of Sun light spread across grasslands generated by Stable Diffusion.
An anime style image of Sun light spread across grasslands generated by Stable Diffusion.

In scripted game worlds, the creative and game design folks need tight control over transitioning between day-night cycles unlike clocked systems we find in RPG games like the The Witcher or Skyrim. While there are many ways to achieve the same, we wanted to simplify the workflow for designers by giving them a uniform way to transition the atmospheric cycles across maps and environments.

Our programmers created a base-class of a trigger volume which the designer could instantiate as Blueprints and place in the level and configure atmospheric parameters made available to the Blueprint by the base class.

When the character enters a particular volume within the map, the atmospheric parameters like Sun-light, fog, Sky-light etc. are transitioned to the new values as configured in the Blueprint instance.

To ensure that the transitioned environment cannot be reversed, we set a flag when the player first enters and, later, if the flag is true, the trigger is ignored. This ensures, for example, that if a player starts from point A in the map which is during day-time, moves to point B which is in the night-time and quickly returns to the volume handling point A, the atmosphere does not suddenly transition back to a day-time.

Below is contrived header file as an example of such a volume.

#pragma once

#include "CoreMinimal.h"
#include "Engine/TriggerVolume.h"
#include "Engine/DirectionalLight.h"
#include "EnvironmentTriggerVolume.generated.h"

UCLASS()
class AEnvironmentTriggerVolume : public ATriggerVolume
{
	GENERATED_BODY()

public:

	class ACharacter* Character;

	UPROPERTY(BlueprintReadOnly, Category = LostFerry, Meta = (ExposeOnSpawn = true))
	bUsed { false };

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = LostFerry, Meta = (ExposeOnSpawn = true))
	ADirectionalLight* SunLight;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = LostFerry, Meta = (ExposeOnSpawn = true))
	FTransform SunLightTransform;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = LostFerry, Meta = (ExposeOnSpawn = true))
	float SunLightIntensity;

	UFUNCTION()
	void OnOverlapBegin(class AActor* OverlappedActor, class AActor* OtherActor);
};

Here we allow designers to select the directional light which represents the environmental Sun-light within the level via the variable SunLight - this is the light which is then transitioned to the values of SunLightTransform and SunLightIntensity when the player overlaps this volume.

The bUsed flag is the one which ensures that the volume is not triggered more than once in order to avoid sudden reversals of the transitioned parameteres.