0
\$\begingroup\$

I am not asking how Minecraft loads chunks or generates chunks, I am asking about individual blocks and entities and their behaviours.

Suppose you have a dirt block: dirt block can be converted to a grass block if there is a grass nearby. The game can have thousands of dirt blocks loaded at the same time, each checking if there is grass nearby.

Now add some monster spawners which have to spawn monsters periodically and keep track of how many monsters it spawned.

Then there is your large field of wheat, potatoes, carrots and saplings which the game also has to check and update every so often.

Then you have your furnaces that smelt your ores.

Then add into the mix all of the animals, monsters, villagers and their behaviours and pathfinding.

All of these actions are happening simultaneously and the game somehow keeps running smoothly on a decent computer.

How do the games generally handle this many block updates and entity behaviours? Does the game keep a list/collection of all the "updateable" blocks and just iterates every so often through that list and simply calls the ".update()" method? How are games with many updateable blocks/entities structured? Updating in a separate thread?

There are so many questions... Any clue is appreciated. Thank you.

\$\endgroup\$
  • \$\begingroup\$ "A decent computer" today can handle a frankly astonishing number of operations per second, so honestly there's probably not much unusual going on under the hood here. The drawing workload is likely much heavier than the comparatively simple update workload. Did you try implementing this in your own game and encounter a performance problem? If so, show us your implementation & profiling, so we can help you identify places where you can improve it. If not, then just dive in and try it: you'll learn vastly more by actually coding than by armchair reasoning about what someone else might have done \$\endgroup\$ – DMGregory Jul 9 at 3:35
  • 1
    \$\begingroup\$ In the case of Minecraft, the engine just uses what it calls "random ticks". A certain number of times per second, a bunch of coordinates are chosen at random within each chunk, and the block at each of those positions is poked, giving it a chance to change state. This is generally smoothed out and slowed down by storing metadata within the block so it can keep track of its own state. \$\endgroup\$ – Quentin Jul 9 at 8:44
  • \$\begingroup\$ @Quentin that looks to me like an upvote-worthy answer. :) \$\endgroup\$ – DMGregory Jul 9 at 16:03
3
\$\begingroup\$
  1. Don't run updates more frequently than necessary. Many of the things you mentioned don't need to be updated every single game tick. The plant growing mechanic, for example, is something where you can get away with checking for updates in intervals of several minutes. If such an update is expensive, then running it might result in a notable freeze for a couple ms. If this becomes a problem in your game you want to avoid, stagger the updates. Instead of updating each block every 60 seconds, update a 60th of all blocks each second.
  2. Don't simulate what the player doesn't see. Minecraft (and many other games like it) divide the world into chunks. The game only updates the chunks which are near the player. All other chunks are suspended to hard drive. When the player returns, the chunks are restored and the time which has passed is simulated all at once. You can often use a very simplified computation model for this. If the player left for an hour, you don't run 60 consecutive "one minute grass-growing updates", you run one grass-growing update where you multiply the grass growing speed by factor 60.

    The same concept applies to timed processes like smelters. You don't actually need to update them all the time. You only need to update them when the player looks at them. When the player opens the smelter UI, you compute how much time passed since the last time they took a look and calculate that there should now be 12 more iron bars and 5 less coal in it than before.

  3. Use the right data structures. This is a very broad topic people have written whole books about, so I am just going to scratch the surface here. But you generally can greatly speed up the computation if you try to represent information with as little data as possible and keep data which is processed together in continuous sections of memory. This greatly increases the usefulness of CPU cache. In other situations, using more complex data structures like spatial hashes, navigation meshes or octrees can speed up certain otherwise expensive operations like collision detection or pathfinding. A skilled and experienced programmer can get a lot of performance out of a CPU if they know what they are doing.
  4. Parallelization is a double-edged sword In the past years, CPUs grew more in quantity of cores than quality of cores. So if you really want to benefit from the capabilities of modern hardware, you need to parallelize expensive tasks on multiple threads so they can run on multiple cores. However, this is often easier said than done. Communication between threads is expensive because that communication needs to be synchronized. And running too many threads at once can create a lot of load on the thread scheduler of the operating system. So poorly designed multithreading can be a lot slower than doing the same work on a single thread. There is also the risk of bugs which only happen in very rare timing coincidences. For example a bug which happens only when one thread finishes one task while another thread is in a critical phase of another task. Such bugs are very difficult to fix because you can't reproduce them reliable and you might be completely unable to reproduce them if you enable debugging tools. This is why I usually recommend inexperienced programmers to stay away from multithreading if possible.

I am wishing you the best of luck with the game you are going to create.

\$\endgroup\$
  • \$\begingroup\$ Thank you sir, very helpful! \$\endgroup\$ – FICHEKK Jul 9 at 10:44
  • \$\begingroup\$ Actually minecraft doesn't simulate unloaded chunks at all, instead they are frozen in time until they get loaded again. This can be a major issue for modded games with automation systems. \$\endgroup\$ – ratchet freak Jul 10 at 9:10

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.