Skip to content

UE4 – Day and Night Cycle for Multiplayer (Part 1)

Accurate Day Night Cycle

Let’s start by creating Day Night Cycle Rules. This will be a structure. We’ll create this in C++. We’re going to make a full C++ version of this project, so this will work as an introduction to Unreal C++.

After this post is published i’ll create another post of full C++ version.

Create New C++ Class:

Select None:

Name it and select Public, make sure you have project name selected from drop down list (DayAndNight_MP), you can also save it in plugin:

Go to xxxx.h file and remove existing class thingy.

Structure layout goes like this, structures need F prefix in their name:

USTRUCT(BlueprintType)
struct FDayNightCyclerRules_cpp {
	GENERATED_BODY()
public:

};

Because we added GENERATED_BODY we need to include generated.h file.

Which in this case is:

#include "DayNightCycle_ST_Rules.generated.h"

Now we can add variables into our structure, inside public. We need UPROPERTY and visibility identifier, like this:

UPROPERTY(BlueprintReadWrite)
bool Silly;

Final thing looks like this:

#pragma once

#include "CoreMinimal.h"
#include "DayNightCycle_ST_Rules.generated.h"

USTRUCT(BlueprintType)
struct FDayNightCyclerRules_cpp {
	GENERATED_BODY()

	FDayNightCyclerRules_cpp()
	: Latitude(45.0f), Longitude(-73.0f), TimeZone(-5.0f), MoonLightStrength(0.05f), MoonDistance(50000.0f), MoonSize(50.0f)
	{}
public:
	//Day Night Cycle Start time from real world
	UPROPERTY(BlueprintReadWrite)
	FDateTime RealWorld_StaticStartTime;
	//Day Night Cycle Start time in game world
	UPROPERTY(BlueprintReadWrite)
	FDateTime GameWorld_StaticStartTime;
	//The Real World Time in Game World Time (24 hours)
	UPROPERTY(BlueprintReadWrite)
	FTimespan RealWorldTimeInGameTime;
	//-89.99 / 89.99
	UPROPERTY(BlueprintReadWrite)
	float Latitude;
	//-180 / 180
	UPROPERTY(BlueprintReadWrite)
	float Longitude;
	//-12 / 14
	UPROPERTY(BlueprintReadWrite)
	float TimeZone;
	//-360 / 360
	UPROPERTY(BlueprintReadWrite)
	float NorthOffset;
	//Display Moon
	UPROPERTY(BlueprintReadWrite)
	bool Moon;
	//Moon light strength, use small values 0,05
	UPROPERTY(BlueprintReadWrite)
	float MoonLightStrength;
	//Moon Distance
	UPROPERTY(BlueprintReadWrite)
	float MoonDistance;
	//Moon Size
	UPROPERTY(BlueprintReadWrite)
	float MoonSize;
};

Delete DayNightCycle_ST_Rules.cpp file and then compile using Compile button in Unreal. Compile button should appear when C++ class is added. If you compile in Visual Studio you have to reopen the project to see changes.

Remove everything from Level Blueprint.

Also add this one too (in same file):

USTRUCT(BlueprintType)
struct FUTCTimeDifference_cpp {
	GENERATED_BODY()
public:
	UPROPERTY(BlueprintReadWrite)
		FTimespan TimeDifference;
	UPROPERTY(BlueprintReadWrite)
		bool SetByController;
};

Add both structures in SynSky.

Add other variables and event dispatchers.

  • GameTimeNow Date Time
  • Sunrise Time span
  • Sunset Time span
  • UpdateSkySpamPrevention boolean
  • IsNight_B boolean

Add two event dispatchers IsNight and IsDay.

This one is FUTCTimeDifference_cpp structure:

This is FDayNightCyclerRules_cpp structure (Replicated):

Go back to DN_PlayerController and finish SendDifferenceToSunSky.

Now in SunSky add BeginPlay event and set DN_Rules. RealWorldStatic_StartTime should be set only on server but in this case it doesn’t matter that much because we have time sync.

Create SunIsDown event, this will help us identify when it’s night and day.

Click for full resolution.

Go to UpdateSun function and set Sunrise and Sunset variables.

So what we want to do is make Game World Time do 100% in x Real World Time.

GameTimeNow variable is where Game World Time currently is. This is where we put the result.

100% of Game World Time is 24 hours.

Let’s define 5 minutes of Real World Time to Game World Time.

We have Real World Start Time and Game World Start Time. And then we have Real World Time Now.

All variables:

  • GameTimeNow (result)
  • RealWorldStart (06/10/2020 21.31.44)
  • GameWorldStart (06/10/2009 15.23.11)
  • RealWorldTimeNow (clock)
  • RealWorldTimeinGameTime 300 seconds

So in 5 minutes 24 hours happens in game.

We’ll take 50% off from that we’ll get 2.5 minutes and 12 hours or 43200 seconds. We can use this to check if our formula is correct.

How much game time has passed in one second? 86400/300 = 288 seconds or 4 minutes 48 seconds.

So 2.5 minutes have passed how much game time has passed? 43200 = 288 x (60 x 2,5) AND THERE WE GO!

GameTimeNow = (86400 / RealWorldTimeinGameTime) * (RealWorldTimeNow - RealWorldStart)

Then we put it all into UpdateRealTime event.

Click for full resolution.

Then add the function to event tick.

The last thing to do is prevent skylight recapturing every frame because that will decrease frame rate. We wan’t to use boolean to do this. We’ll set boolean to true after some time and after recapture.

If you didn’t remember to clean up Level Blueprint do it now.

And test it! The Sun should do a full circle in 1 minute with these settings.

Pages: 1 2 3 4
Subscribe
Notify of
10 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
kilokillzall

where did that “Update SunSky” function come from? is that an older version of Sun Position Calculator?

kilokillzall

oh shoot posted this on the wrong page

lvlmaster

Do you mean “Update Sky”? Because i can’t find “Update SunSky”.

Unmodified version looks like this:
comment image
In 4.26 and 4.27

This was probably made in 4.25. Because Epic added “Real Time Capture” into SkyLight
comment image

https://docs.unrealengine.com/4.27/en-US/WhatsNew/Builds/ReleaseNotes/4_26/#real-timeskylightcapture

Which is why “Update Sky” is not in 4.26 and latest:
comment image

bonkimaslo

Do you think this will be the proper system for Unreal Engine 5 as well? Or did they add some new way to do it even better?
Thanks for your hard work

bonkimaslo

For some reason in UE5 you can’t add Make Timespan and Date Time as they are incompatible

lvlmaster

Make sure you got the variable type right, best way to do variables is to use “Promote to Variable” which you can get by pulling out from endpoint.
In this case find AsTimespawn (text) or AsTime (text) and try pulling out from these to create variables.

https://docs.unrealengine.com/4.26/en-US/BlueprintAPI/Utilities/Text/AsTime/

https://docs.unrealengine.com/4.26/en-US/BlueprintAPI/Utilities/Text/AsTimespan/

bonkimaslo

Thanks for the quick responses, appreciate it!

It seems like a UE5 bug to be honest.
When I drag Server Game Time to A position (Date Time structure) of the ADD node, the B position shows that it’s timespan structure, which it should be. But when I connect the Make Timespan endpoint to it, the A (Server Game Time) connection is broken, and it changes every pins structure type to timespan.
I found some other post showing the same problem :
https://forums.unrealengine.com/t/adding-timespan-to-date-time-not-working/256329

Sorry to spam your tutorial about UE5 stuff, I might have to build it in UE4 and migrate to UE5 to make it work

lvlmaster

Oh yeah, i found the same thing from UE5 EA2, it’s actually missing Date Time and Timespan combining/add node.

You could create Blueprint Function Library in C++ and then create custom function which combines them and returns result or… just try the full C++ version:
https://levelparadox.com/2020/11/13/ue4-day-and-night-cycle-c-part-2/

you just need to create material, material instance and 2 curves and it should work out of box.

Add me on Discord if you need more help: nuclearlocket#9741

bonkimaslo

Haha, I waited with messing around with it until the actual release of UE5, but it seems like they didn’t fix this issue, this node is still bugged for me.
I have no experience with C++ in Unreal, but gonna give it a shot, thanks!

lvlmaster

Well haven’t seen anything new or better anywhere else and seem’s like everyone else is also using Sun Position Plugin tools to do Day Night Cycle in UE5. Even in UE5 + Lumen you still need Sun Position Plugin, Exponential Height Fog and Sky Athmosphere if you wan’t Dynamic Day Night Cycle.

This project in UE5:
https://www.youtube.com/watch?v=nkPnIlPtg8Y

Someone else using Sun Position Plugin in UE5:
https://www.youtube.com/watch?v=kcV5XOqX9i8

Level Paradox
10
0
Would love your thoughts, please comment.x
()
x