I have recently been spending time on getting the progression cycles and game play loops going. Part of fleshing this out is to give the sense of playing through a day and all its dangers then shifting gears at night when different insects come out and opportunities are aplenty for a skillful survivor. Building the cycles was not without its challenges and hopefully anyone dealing with the same may find this article helpful.
Blending the Skybox
This was an interesting challenge and one I couldn’t do without a bit of help. After a bit of research I was able to find references to a a shader that allowed for blending between 2 skyboxes and included a fog. As part of the swing between day and night you can lerp between 0 and 1 where each extreme is 100% of either the day or night skybox and 0.5 is a blend between the two. If you want to check it out have a look here.
Rotating the Sun
On face value this seems like an easy problem to solve but I had to think about it for a while as when a additional players joins they need their sun set correctly on their game client so that it matches the server, and if for any reason a player needs to go to debug mode and change the time they can. I made the below demo where I manipulated the time to show how the sun will flick between stages.
One of the reason the reason I had big problems with the cycles was putting the sun at the right spot it the sky. If you take time of day as a percentage of a whole day you can multiply it by 360 which gives you its angle in a circle. But when you know where the run should be and need to move it there smoothly you need to also know where it is now. This is where the problem comes in, if the sun has passed it’s half way point, the angle between 2 vectors does not return a value greater than 180. So what I needed to do was the below.
var angleWhereShouldBe = (((timeOfDay / dayLengthInSeconds) * 360) -90) ; var localAngle = Vector2.Angle(Vector2.up, sunLight.transform.localPosition); Vector3 cross = Vector3.Cross(Vector2.up, (Vector2)sunLight.transform.localPosition); if (cross.z < 0) localAngle = 360 -localAngle;
Basically if the sun is passed the half way point (determined by if the cross product of the 2 vectors returns a negative) then deduct the angle from 360. This gives you the correct angle.
It is also worth noting that I had issues with the concept as I was thinking about the vectors in 3D. The reality of it is that the sun only needs to rotate around on a single plane so its z coordinates are irrelevant. If you did want to do something fancy around the z I would suggest still using the above and a sine function of time to calculate the z position.
Other points of change were the sun needs its intensity changed over time which can be a simple lerp function for 1 part of the day. This gives the impression of a sun rise and sun set as the light increases or softens. I also adjust the ambient light using the same method so that I can get a more orange ambience during the day and softer blues at night. The sun needs to follow the player so I attached it as a child of a game object with a basic follow script to the local player. And finally, as the game is intended to be multiplayer there is a synchronise function to ensure that clients are at the same point in time.
I hope this has given some insight in to the thought process needed to solve the cycles and if you want to check out what the end product looks like see the below video. Also worth mentioning that it will be a lot better once Matt has given it the artist pass in the future.