Spawners and Groups - MegaPunkGames/MegaBoidsDemo GitHub Wiki

Spawners

In the previous pages, we explained the different elements that come together to create movement in a boid. Multiple times, we mentionned thae fact that some boid properties does not belong in the boid configuration data asset. Most of the time it is because the boid needs some reference to a level actor or we want them to have environment specific behavior. To do so, we can specialize our boid configuration from inside the level, through it's spawner.

MegaBoids spawners are an actor class that you must place in your level in order to spawn a group of boids. When we spawn a batch of boids, we are actually spawning a group. Boid within a group share a set of properties for the duration of their lifetime. It includes their bounding box, an optional space partition and specialized driving subprocessors among others. The whole set of properties is listed below:

image

Parameter Description
Spawn on BeginPlay Should it automatically spawn the group on BeginPlay?
Spawn configs List of boid configurations to spawn within the group.
Initializer subprocessors List of initializers used to setup the boids in the spawned groups.
Driving subprocessors List of driving subprocessors to specialize the boids in the spawned groups.
Obstacles List of environment obstacles used for avoidance.
Obstacles color Color to render the obstacle shapes in editor.
Use space partitioning Should the spawned boid groups use a space partition? More details below
Grid cell size factor If using a space partition, multiplier on the size of the boid to use for the space partition grid cell sizes.
Max boids per grid cell If using a space partition, the maximum number of boids tracked in a cell. When the cell this amount of boids, new boids entering it will simply be left out. They can therefore get information about their neighbors but are "invisible" to them. This can however provide a significant boost in performance with minimal impact on the simulation.

Groups

The first thing to know about groups is that they are all independent from each other even if originating from the same spawner. Every time you spawn a group, it will live in it's own bubble without knowledge and communication with other groups. This is a conscious decision we made that allows us to achieve better multi-threading performance since we can process groups in parallel tasks. Groups also share common data like obstacles and having this data confined only to the boids who use it also reduces the required processing. It appears limiting at first, but it's really not when you consider composition. We also don't expect a large number of groups to be active at any given time. Let us know if you come to different conclusions or have different needs.

Group Composition

At this point, you possibly think that the spawner takes a boid configuration and spawns a batch using that template, straps a few extras on and we're good. Although not far from the truth, the spawner has an extra trick up its sleeve: it can create boid subgroups of the same or a different configuration. This opens up so many possibilities for complex behaviors, some of which we already touched on in the anatomy page. Keeping in mind that there is no interaction between groups, the spawner allows group composition and entities within a group can interact. This means you can actually have cool designs like a hundred small fish roaming around a pool of shark or different personalities for a entities within a clowder of cats. Coupled with different representations per boid configuration, you can achieve incredibly realistic results.

[!Note] When compositing boids of vastly different sizes, that larger boids automatically ignore the "considerably" smaller ones. Just like a dragon won't budge for a goblin, your boids will behave organically!

image

Space partition

Space partitioning is a technique commonly used in video games to improve performance. Many operations in a game AI require to search the surroundings to find entities near you. Boids do this extensively when searching for their neighbors in order to compute basic steering forces. When we deal with thousands of entities, it means each boid needs to compute the distance with every other boid in the group, making for millions of operations. Partitioning the 3D space in cells allows us to only consider the boids in cells near our position and therefore making it manageable.

The cell grid is a good optimization, but can only help so much when all entities are tightly packed. A further improvement available is that we can limit the number of boids in each cell. If a cell contains more than the specified number of boids, some of them will simply be ignored from the steering calculations. Of course, it comes with an impact on the separation part of steering especially since boids can't separate from neighbors which are not tracked in the space partition. Cohesion and alignment aren't impacted as much since past a certain threshold, each boid's impact becomes fairly small. Finding the right balance is key here.

[!Note] The space partition uses a respectable amount of memory. It is not currently optimized for memory usage, but rather for processing speed. Make sure to check your memory usage when using a lot of space partitions.