0

I am working on a voxel game similar to Minecraft. The goal would be to handle more entities but also offer a more immersive experience by the fact that the player does not need to worry about loading chunks. What is a way to handle unloaded entities? I plan to keep chunks near the player "awake" and performing a full simulation. However, I cannot do this for distant chunks, it would require too much computing power. I was thinking about discretizing some of the entity behavior, but this appears to become very complicated once there are too many possible interactions. Imagine a furnace processing ores, which in turn go into a chest, and a golem moves items from that chest into some other container. The simulation could probably be simplified the more distant from the player it is, but obviously I want to avoid anything that could lead to item duplication. Are there any elegant solutions to this problem?

Philipp
  • 119,250
  • 27
  • 256
  • 336
  • You may be interested in Designing persistence in an ECS world subdivided into chunks. There are also some relevant techniques discussed in this question about Factorio-like sim games. Ultimately, the amount you can simplify these background calculations depends on the complexity of your mechanics. If your mechanics are Turing complete (a surprisingly low bar to hit in games!) then there may be no guaranteed way to achieve the same net result without simulating every tick. – DMGregory Nov 28 '23 at 18:47
  • @DMGregory thanks for your response. Including more complex things, I wish to reimplement redstone, which is Turing complete. – Daniel123455 Nov 29 '23 at 11:55
  • Multithreading is usually the answer when you want to avoid loading screens or hide the loading artifacts from the player – Cherestes Radu Nov 30 '23 at 13:11
  • An elegant solution may not be a fast solution. That depends on how you define elegant (for example, we could ask "Elegant from whose perspective? Developer? Player?") Are you primarily concerned with performance? – Engineer Nov 30 '23 at 22:42
  • @Engineer, yes fast and working well. in modded minecraft, the player is sometimes painfully reminded about the limitations when he has to choose which chunks are loaded. factorio on the other hand makes everything seamless – Daniel123455 Dec 19 '23 at 19:39
  • @Daniel123455 Right. Minecraft's slowness is primarily a consequence of the game being a jack-of-all-trades but a master of none. If all they had wanted was to implement a Turing machine, it would have arguably been several orders of magnitude faster. The first reason for this would be the amount of data stored per column / voxel being rather large in Minecraft. More recent voxel games have arguably learnt this lesson and chosen more carefully what they want "a voxel" to be. Implicit data (which can be recalculated on the fly) is also way faster than storing everything. – Engineer Dec 21 '23 at 01:13

1 Answers1

2

One technique you can use to optimize things like crop growth or furnace smelting in a Minecraft-like game is to, rather than have a loop that goes through all of them and updates them in accordance with the current time every frame, to just store the time they were created.

For example, for the furnace you can just store the items in the furnace, and the time at which the smelting started. And then, whenever the furnace is accessed next, calculate how many of the items should have been smelted by subtracting the stored start time from the current time. 0 (or close to 0) computation is required for all the intermittent time.

A similar technique can be applied to crop growth. Calculate their age on the fly as needed instead of manually updating them constantly.

CPlus
  • 143
  • 11
  • 1
    In fact, you can even implement furnaces this way all the time. Minecraft itself has an inefficient version of furnaces, which check for updates every tick. But (unless it's hooked up to automation using hoppers) you only need to check when a player looks in the furnace, and if it's automated, you still only need to check every 20 seconds, when something finishes smelting. – user253751 Dec 02 '23 at 17:45
  • @user253751 The only catch I see is how one could make the furnace use the dark texture instead of the fire one once the smelting is complete. What if I sent the current game time into the uniforms of the shader, and the creation time of the object with the quad-specific uniforms somehow, and then selected the appropriate texture in the vertex shader? No branching would be required because I could just add the boolean to the array index if I am using an array texture. Another potential advantage of that is not having to rebuild the chunk mesh every time a block 'updates' in this manner. – CPlus Dec 02 '23 at 18:00
  • 1
    Or you start a timer to run out at the time when smelting finishes, to change the furnace's texture. There are lots of things in a game that happen at a certain time, so you can have a master list of timers, and if you keep them in sorted order (or use a min-heap) you don't need to process all of them every tick, only the first ones. – user253751 Dec 03 '23 at 13:08