Chris Johnson - Game Designer

Fluid Dynamics Simulation Prototype

fluiddynamics_cover

Fluid Dynamics Simulation Prototype

A particle-based simulation of the physics of gases in the air

Status: Complete

Developed By: Chris Johnson

Engine/Framework: Unity 5

Platform: PC

Type: 2D Technical Prototype

This project was a 3-week experimental prototype I built to investigate methods of simulating fluid dynamics in a video game. Many methods of simulating fluid dynamics already exist, but most are for the purpose of scientific simulation, and are too complex and computationally intensive to fit in a game. Despite this, I believe a simulation method that was viable for use in games would have the potential to allow some very interesting game mechanics. My objective was to find a method of simulating fluid dynamics (specifically gases) in a way that was computationally efficient, but would still yield somewhat realistic behavior.

My proposed solution was actually inspired by research I had done several months before on boid flocking behavior. Boid flocking is a type of AI-driven navigation of large groups (“flocks”) of agents. Each boid takes in weighted inputs from three simple rules:

Boid Flocking Rules:

  • Separation: each boid must avoid getting too close to another boid
  • Cohesion: each boid must stay close to the center of the group
  • Alignment: each boid must move in the general direction of the group as whole

I noticed that when I increased the weight of the separation input and lowered the weight of the other two inputs, the boids would, over time, move from areas of high boid concentration to areas of low boid concentration, just like gaseous particles in the real world. I determined that if I created a particle, much like a boid, that moved based on a number of weighted inputs, that I could make them behave much like gaseous fluids, even if the behavior is not completely true to real-life fluid dynamics.

gif2_compressedAn early implementation of test particles with separation, collision, and ambient turbulence inputs applied

So, using Unity 5, I created a gameobject prefab of a small circular sprite. I gave it a primitive circular collider, and Unity’s rigidbody2D component. I used rigidbody component because, to move the particle in a way that accounted for drag, I would be calculating a force impulse on each frame and passing it to the rigidbody component, which would move the particle appropriately. (For reasons I will discuss later, this is perhaps not the best method of moving the particles) I then added a script which would implement my weighted inputs based on the following rules:

Gaseous Particle Rules:

  • Separation: each particle must avoid getting too close to another particle. The shorter the distance to the closest neighbor particle, the greater the input to move in the opposite direction. This means that particles will move outward from one another until they occupy all the available space with optimal separation from one another. This also means that particles in “high pressure” areas (areas with a high concentration of particles) will move into “low pressure” areas (areas with a low concentration of particles).
  • Gravity: each particle is heavier (or lighter) than air. My method allowed me to assign different specific gravities (SG) to different particle types, and they would behave and interact accordingly. For example, in a mix of “Oxygen” particles with an SG of 1.1044, and “Methane” particles with an SG of 0.5537, the mix would eventually separate, and the lighter methane particles would rise above the heavier oxygen particles.
  • Collision: each particle has a collider, and collides with walls and with the player. However, particles do not collide with each other, as I found this led to unrealistic behavior. This collision ensures that particles can be packed into a confined space without escaping, essentially creating a compressed, pressurized area within that confined space.
  • Ambient Turbulence: each particle may, at any time, receive a minor impulse in a random direction. This roughly replicates a real-world effect of the same name, in that air is never completely still and without external input. It is because of this phenomena that the air in the atmosphere remains a homogeneous mix of gases, rather than separating itself over time into it’s respective elements and compounds based on each’s specific gravity (SG).
  • External Force: each particle must move with respect to an external force. This rule is implemented as a “shortcut” to achieve more realistic behavior at a lower computational cost. I can create volumes in-game that represent, for example, force being applied from a spinning fan. When particles enter this volume, they are passed an external force input. The magnitude and direction of this input varies depending on the particle’s location relative to the “origin” point of the force, in this example the blades of the spinning fan itself.

After implementing these rules and tuning the weights of each of them, I achieved some satisfying results.

gif1

A group of particles being spawned. The mix is simulating air containing methane. Blue particles are nitrogen, red particles are oxygen, and yellow particles are methane.

fan

Particles being pushed by the external force of a moving fan. The volume of the external force is represented by the green quadrilateral.

gif3

Particles separating to evenly occupy a space.

This experiment had gone well so far, but there were a few other features I wanted to experiment with. Firstly, I wanted a tool to place particles. I had started by placing them by hand but that method proved very tedious, especially when specific mixes of air were needed in certain areas. So, I created a prefab tool to spawn them. It is the standard size of one grid space in my game. It is placed where the particles are desired, and the designer specifies the air pressure, and the composition, in the form of a list of particle types and their percentages in the air. When the game starts, the prefab calculates which particles to spawn, spawns them, then destroys itself.

tool

Tile-based tool for spawning particles

Next, I wanted to experiment with a mechanic based on fluid dynamics. In the real world, certain mixes of elements and compounds in the air can be highly combustible, depending on the concentrations and ratios of each. In the engineering and scientific world, this relationship is expressed via a “flammability diagram.” The flammability diagram for Methane in air is shown below:

A more detailed explanation of flammability regimes and the stoichiometric ratio is available here. My goal was to replicate the real-world behavior that this diagram explains. Though it proved mathematically intensive, a solution was found. The result:

  • Particles can only ignite if they exist in the proper area around the ignition source.
  • Combustion requires oxygen. As such, it will not occur below a limiting oxygen concentration (LOC), and higher concentrations of oxygen will allow for more combustion
  • Even if a particle type is known to be flammable (like methane), it will not ignite if it’s concentration in the air is too high
  • When a particle combusts, it consumes itself and oxygen in the stoichiometric ratio (in the case of methane, this is 1/3 methane to 2/3 oxygen)
  • When a particle combusts, it expands, pushing surrounding particles outward
  • When a particle combusts, it leaves behind the by-products of combustion, carbon dioxide and carbon monoxide
explosion

Combustion occurring in a mix of methane and air. The correct ratio of methane (yellow) and oxygen (red) combust, leaving behind carbon dioxide (green) and carbon monoxide (black). Note that, like the air we breathe, this air contains about 78% nitrogen (blue), which is not affected by the combustion.

I was very pleased with this solution. It replicated all the major aspects of combustion that occur in the real world, and has viable potential for implementation in games.

Lastly, I wanted to create a method to analyze the composition of the air at any given point. In part, this functionality already existed in the ignition source, which needed to analyze air composition around itself to determine if the air was combustible. However, I wanted to analyze the air at the player’s location. In the real world, humans are accustomed to breathing the air in our atmosphere, which contains the ~21% oxygen that our bodies require. Places with more or less than 21% oxygen are referred to as Oxygen-Enriched Environments and Oxygen-Deficient Environments, respectively, and can be very dangerous. Breathing air with less than 21% oxygen is unhealthy, and breathing air with less than 16% will cause hallucinations, incapacitation, and eventually death. I’ve often thought about the viability of turning this real-world phenomena into a game mechanic. So, I created a script to analyze the air composition at the position of the mouse.

aircomp

the air composition being calculated at the mouse position

The most simple way to turn this into a mechanic would be to drain the player’s health when the area they are in contains less than 21% oxygen. Currently the sample radius is very small, so the concentrations fluctuate greatly. But with some smoothing of the values, this could be a viable game system.

However, this experimental prototype has a weakpoint: it requires a great deal of computational power. By adjusting Unity’s timestep settings, I was able to achieve a framerate of 28-29 FPS with 1,071 particles on the screen. There are several causes for this:

  • On each frame, each particle must calculate which particles are close enough to be it’s neighbors. This requires a 2D circlecast for each particle on each frame.
  • Physics and movement is handled by Unity’s RigidBody2D component. This is perhaps overkill for such a simple particle behavior. A minimalist, purpose-built solution would be better.
  • Through my research, I have found no viable way to implement GPU acceleration or compute shaders for this project in Unity. If GPU acceleration could be used, I believe it would improve performance greatly.

In conclusion, this experimental prototype has highlighted that this method of simulating fluid dynamics has both the great potential for use in games, and the great need for further optimization if it is to be performed at runtime.

Game Design Portfolio of Chris Johnson