I figured it’s about time to start tracking my progress with this project – after several months of engine development I’ve got something visual to show off:
I’ve been building a general purpose grid-based simulation engine in Unity – it’s a 512×512 grid of data, processed with multiple background threads. Every cell in the grid is a discrete piece of the world – it has a specific height, color, composition and contents. Terrain shape is generated with Perlin noise – using this excellent port of LibNoise for Unity.
So far – so standard. The fun parts of offloading computation to different CPU cores and having a GPU that can crunch copious amounts of triangles per frame are not apparent at this height – so let’s zoom a little closer.
Every cell in the world can contain one or more entities – if a cell itself is a cubical volume of space, the entities are the objects contained in that cell – plants, animals, gases, fire…
We can already see the objects that make up the world – a rather large amount of sprites, one for each simulated entity.
For every entity in the world I render a textured quad 60 times per second. There’s absolutely no visibility calculations or caching of results. Surprisingly enough, this incredibly brute-force approach has actually worked pretty nicely, performance-wise! (not an excuse)
Of course, doing this requires a few tricks and workarounds, especially if you happen to be using Unity. I’ll go into more detail on threading and rendering in further posts – I’ve often seen people claiming that it isn’t possible to do multithreaded applications in Unity, which is only half-true. It’s definitely possible, just…not recommended at this point in time.
Let’s take a closer look.
Another property of cells is that while they themselves have discrete coordinates, their contents do not. An entity can be positioned anywhere inside the
[-1.0,1.0] range of its parent cell. And as I already have a frequently updated quad renderer, I can increase the apparent fidelity of the simulation – objects can move smoothly between cells and aren’t always confined to to cell centers. In this way I can have my cake and eat it too – finely grained positions for entities and roughly grained connectivity, nesting and proximity information of cells.
Without delving too much into why I’m building this simulation, I think it’s time to provide a first public tech demo:
BioGrid 0.0.1 (Windows)
- Mouse Scroll – Zoom
- WASD/Arrows – Pan
- constantly lose energy
- move around randomly
- eat plants in their cell
- gain energy of the eaten plant
- reproduce after gaining enough energy
- die when touching water
- die when out of energy
- constantly gain energy
- spread to empty neighbouring cell after gaining enough energy
- don’t spread on sand and snow
It’s a rather simplistic herbivore/autotrophe simulation, but the secondary effects of simulation scale are already (kind of) visible. Certain plants or animals can dominate an area, and rarely, populations on small islands are wiped out. Low-lying areas bordered by beaches and water tend to act as nature preserves – most animals in these regions end up wandering to the ocean before doing any real damage.
While there are 4 visual varieties of both herbivores and plants, and they’ll pass on their smashing good looks to their offspring, they are functionally identical.
It’d be really nice of you to let me know of any suspicious crashes and general performance woes – the sim should be relatively stable, but threading bugs can be subtle…