My Day/Night Cycle Snippet - Asking for Feedback :)

Hey y’all,

I posted my first snippet, a day/night cycle, :sun_with_face: :last_quarter_moon_with_face:, and since there are no comments in the Snippets section I was wondering if I could get some feedback here on my work. I’m new to programming so I kept things simple. Here’s the webpage for my snippet. Basic Day/Night Cycle (For Beginners) | Uefn Code Snippet

In particular I’m looking for advice on how to make my comments in the code as clear as possible, with correct terminology. Also lemme know if there’s a better way of accomplishing what I was trying to accomplish. The code does work.

Thanks! Also thanks to Jay Villanueva for the Office Hours lesson that inspired the loop.

2 Likes

Hi BlueClairy,

I took a quick look and it seems pretty clean to me. Some (very minor) comments:
Names like PopUp_Sunrise are certainly fine and clear. Internally at least we are trying to keep our naming schem to use PascalCaseWithNoUnderScores for the names of values/fields/functions/etc while using snake_case_for_types.

You are certainly free to use whatever scheme YOU like in your own code, but if you wanted things to look the same between your code and our framework code you might rename things like that PopUpSunrise instead.

Also, you can’t do this YET, but we are going to be gradually adding the ability to modify certain properties on certain devices at runtime. So a couple months from now you’d probably be able to have just a single popup device and set the correct message on it in your sunrise/sunset routines. Having two right now though is correct as you must do that. :slight_smile:

I think your use of Sleep and to keep this loop going is great and totally inline with what we have in mind for people to use coroutines for.

Later you might want to find a way for other code to query ‘exactly’ what time it is in your day/night cycle so that could be a fun thing to think about as you expand your code.

3 Likes

Thanks so much for the feedback, Waurelius!

Good reminder about PascalCaseWithNoUnderScores. I updated the snippet with that format, because it’s a useful habit to keep everything standardized, especially for collaboration purposes and for sharing.

Modifying properties at runtime sounds amazing! I love the idea of cutting down the number of redundant devices.

Glad this is a good use for Sleep. I picked that section up from Jay’s Office Hours lesson on Verse.

Querying what exact time it is in the cycle sounds super useful for my purposes! Would an example of this be a shop that only allows players to open the door between whatever is my cycle’s equivalent of noon to 5 PM, instead of all day? I love dynamic worlds that behave differently at different times. Are you willing to share what I should look into to get started on this?

Would an example of this be a shop that only allows players to open the door between whatever is my cycle’s equivalent of noon to 5 PM, instead of all day? I love dynamic worlds that behave differently at different times

Indeed this is a great example of something you could do with this information. :slight_smile:

Are you willing to share what I should look into to get started on this?

Well there’s a number of way to skin this cat. One of the simpler ones is not possible right now because we don’t expose the ability to query the current state of a game or system clock from the engine. (Some day…). For the sake of my preferred solution I’ll describe it though. When we do expose something like GetCurrentTime() I’d recommend simply storing the ‘currenttime’ in your OnBegin and calling that something like ‘StartTime’. If you had that you could always call GetCurrentTime() again later, subtract out StartTime, and use that to calculate your current ‘gametime’ depending on how many seconds you wanted each day to last or whatever.

Now, as with most things in life this could get more complicated easily. ie, maybe you don’t WANT your gametime to start whenever the ‘OnBegin’ happens to get called for this device. Maybe you’d want to reset that start time later. Maybe eventually this game runs persistently for years and floating point drift starts to make your time calculation more and more inaccurate over time. (Verse uses 64bit floats so this is less of a problem that it could be, but still…). Regardless, this would probably be the simplest first thing to do if we actually let you query the system time. (Which we don’t at the moment for… reasons. :stuck_out_tongue: )

Ok now for some actual useful suggestions!
Really your solution here depends on ‘How precise do you want your time query to be?’
For example, you could create a mutable float, var CurrentTime : float, set it to 0 in OnBegin, and use the ‘Spawn’ function to launch a NEW function that does Sleep(1), and each time it wakes up, just adds 1 to CurrentTime. (Perhaps you would want to Mod that by your DayLength so it stays between 0 and DayLength as opposed to getting really reallly big). Then in any of your other code you could always ask your Device what ‘CurrentTime’ is, and it would be precise to whatever period of time you were sleeping in your new Coroutine (the function you Spawn’d).

You could also skip spawning a new function and just change the Sleep amount in your OnBegin function to be a smaller length of time to do the same thing, and check the time afterwards to decide whether to flip your light on/off. Either way would do the same thing, just spawning an extra function maybe makes the main function a little cleaner to look at.

In addition for your example of allowing players to open doors at specific times, you could also imagine two ways (really a LOT of ways, but I’ll stick with two) to implement this.

Assuming you could ask your device what time it is, you could have the door’s logic ask for the time and calculate if it can open or not every time the player tries to open it. Totally reasonable way to implement this. What’s nice is you only pay for that calculation whenever someone tries to open a door. This might be very rarely, and only a few doors, so awesome!

However, if you had say, millions of doors, and millions of players trying to open them constantly that calculation would be very redundant and costly. If you had a case like this, it might make more sense to send out an ‘event’ at various meaningful times. So you could have the door ‘subscribe’ to your timekeeping device, which would signal that event at say, 5PM to say closing time! All the doors would wake up just once at 5pm, and do some handling. For instance to change some internal logic variable to like ‘set IsOpen := false’. That way it can locally cache whether it’s open or not, and only update it infrequently at meaningful times. This is more complicated though and I’d really recommend the first method to start.

Sorry for the big wall of text, but I wanted to try to illustrate the idea of making a choice in the tradeoffs of various approaches, and when you might choose one over the other.

1 Like

Wow thanks for taking the time to explain! I’m taking a break from logic this week to focus on art, but I’ll return to this :eyes: Definitely I only have a few doors for now.

I don’t know if you’re familiar with the Gamecube game Chibi Robo, but my world is partly inspired by that. In Chibi Robo you’re a tiny cleaning robot who lives in a home with giant human NPCs. The day/night cycle is very important because the NPCs follow regular schedules for where they hang out and how they behave, and some activities and areas are only available to the player at certain times in the day/night. The game meant a lot to me growing up and I think UEFN is a good place for a tribute. :blue_heart:

Shout out to @jay_villanueva for inspiring devs to create handy scripts like this one. Thanks for calling it out BlueClairy. Feedback in all shapes and sizes, even knowing when something was helpful makes an impact.
I thought I played everything on the GameCube, but I’ve never played Chibi Robo. I look forward to seeing your version of it.

2 Likes

Ya I think the lesson helped a lot of us! Thanks for the encouragement about my game :slightly_smiling_face: