I was brought on board the Age Of Survival (greenlit on Steam and Early Access release on August 25th) game development team and my first task was to create the AI for the animals. The game is set on a island with African fauna and as a player the objective is to survive after being marooned there. There are sea, land and air fauna that comprise both predator and prey as well as animals that are not predator but would not be easy prey such as hippopotamus. In any animal ecosystem the balance is struck between predator and prey and can be mathematically modeled such as with the Lotka–Volterra_equation. Basically stated that as the number of prey based on local environmental food resources increases to a max the number of predators increase to the point they overtake the rate of the prey’s growth and the number of prey falls and the number of predators diminishes due to lack of food resources. At a certain minimum point the number of predators is not enough to overtake the increase in the growth of the prey populations and the predator populations increase again following and affecting dynamically the growth curve till the maximum is reached. Modeled as a graph over time they look like offset sine waves with slight perturbations. A base set of metaphysical dynamics that could be modeled virtually and used to drive animation controllers for visualization of the simulation would be needed to develop a framework around which these main relationships evolve.
The Predator Prey Dynamic
So the first task was to create solitary predators and groups of prey and model the basic metaphysical dynamic of detect -> pursue -> capture for the predator model and detect -> elude -> return to group for the prey. When not involved in the predator <-> prey dynamic they would go about navigating. Since herds of African animals generally migrate from feeding area to feeding area the best method to choose was waypoint to waypoint navigation. Beyond simply navigating directly at a default speed they would necessarily want to group together socially for protection when attacked by a predator who can cut them out and capture them much easier when they navigate solo away from the herd. Since there may be hundreds of animals in simulation at any given point the main thrust of any controlling behavioral algorithm is to not overload the calculations forcing the framerate to drop to whatever are considered unacceptable numbers. To facilitate cohesion or grouping I needed to calculate the heart of the herd and update it based on the average positions of all active members of the herd but it was not critical to have this information every frame so it is calculated once very couple of seconds. A separation radius was given as both an obstacle avoidance and a herd member separation distance and this was calculated every frame in the navigation function. If a member of the herd is within the cohesion radius which center is located at the average center of the herd they travel at the default or what might be considered a relaxed speed. If the average center is calculated to be relative forward of the herd member and beyond the cohesion radius they speed up to catch up with the herd. If it is behind they slow down to allow the herd majority to catch up. This gives a nice and natural dynamic to the herd’s navigation as a whole.
The predator navigation dynamic is fundamentally the same as far as navigation by waypoint but as in real world predator ranges these should be set much farther than the herd waypoints max distance from the herd’s origin. Basically the herd wanders a fixed circuit whose max distance from it’s origin is smaller than the max distance of the predator’s circuit waypoints from it’s origin. In the tech demo if the lion has waypoints that continually cross the range of the zebra he can wipe the herd of 50 out in a half hour or so. Once the predator has detected prey within the prey detection radius it immediately begins pursuing them. The prey has a predator detection range set so that they will begin moving away from the prey at a higher detection radius. However they have a reaction scanning interval so they may be a bit late and then the predator can cut them out of the herd. The predator scans for the closest prey and pursues that until beyond detection range or captured. This works out nicely when in a herd as the predator may choose several possible prey to lock in on before cutting one from the herd.
The land prey to land predator dynamic is very similar to the sea prey to sea predator dynamic with the exception that the sea animals can react in a 3D volume of the ocean as opposed to the 2D surface of the terrain. There are of course exceptions to this general rule and we will get to them.
Being that we may wish to find out any data about our FaunAI simulation a central registry component for each created actor and group of actors was needed. Enumerations were set up for FaunaName, BodyType, Sex, Habitat, Category, Type, Diet and SocialGrouping. As each animal actor was created it registered with this component which placed it in one of several arrays such as seaPrey, landPredator. Each groups manager parent component was also registered separately to facilitate rapid culling should the overall total simulation calculations become burdensome on the framerate. For example, should we need to turn on or adjust culling and we know we are on land we can retrieve the lists of land predators which should not be a large data set. That list is iterated through and the distance found from the main camera. If the distance is greater than the camera culling radius the member is set to inactive. Groups are handled differently in that even though a group parent manager may be beyond the culling radius it’s members may be inside the culling radius. Ergo they would need to be included in the active simulation. All it takes is one active group member to include the group parent so once that is found the search loop can be broken out of to save calculation cycles. Those that are in range are now in a separate culling list which data can be grabbed and modeled. To further reduce the calculations and stagger them this culling algorithm takes place after the camera has moved so any units from a preset position. Once it is beyond the distance the position is reset and the culling algorithm occurs.
The Wildlife Manager component can also be queried to make heat maps showing concentrations and navigation routes of various groups and solitary fauna. Data such as capture locations, predator to prey ratio along a timeline, current group sizes per fauna type can be modeled and various parameters adjusted to achieve a well balanced ecosystem where populations of any kind do not exceed a maximum nor go extinct. The weight of each animal is also calculated upon registering so total mass and individual weight can be read out for any need or reason or just to make another cool looking heat map for analysis with:)
Birth and Death
When a prey is captured it is set to inactive so as not to interfere with the simulation calculations as far as navigation and eluding of prey nor feeding is concerned. However if prey are not replaced they can simply “go extinct” once the last of their kind is captured. Ergo at a certain ratio of created herd size to current herd size “births” begin to occur every so often until the max herd size is again met. A the time one of the inactive herd members is set to active and it’s behavioral parameters are set by the average of all still active members of it’s group. This gives a kind of genetic inheritance that affects the ongoing simulation. When the members of a group are first created they take default parameters from the managing parent and multiply them by a range slightly below and above unity. This gives each member slightly different characteristics. When rebirthed they use the averages of the remaining members for setting their parameters. This may mean that all remaining members were given slightly higher default and maximum speed levels and greater turning speed which would then be averaged and used to set the rebirthed animals parameters which again would be multiplied by a range making it faster still or slower than the average. This leads to a continually evolving simulation via looping feedback…naturally.
Endurance and Hunger
Some things have to be taken into account for corner cases and yet still remain to appear as “natural” behavior. For example, during testing the lion would successfully cut out a zebra from the herd but due to the original distance and the zebra adjusting it’s trajectory both the lion and zebra would run off the edge of the test terrain. Now, in the real world the reason that most predators can capture prey whose top speed exceeds theirs is endurance over the long haul. So they were given an endurance parameter with a value of one as that is good to use when used as a multiplier of other numbers in conjunction with several other multiplier variables. When pursued and running at maximum speed they have a hard time breathing so each FixedUpdate a small fraction was subtracted from the endurance value which the maximum speed was multiplied by. This was tuned so that the pursuit and capture happened within a reasonable distance from the start of the chase.
For a predator to not just run hog wild in the simulation and kill everything in detection range or conversely have a range that just will not overlap the herd for extended periods a model would have to be chosen that accommodated both solutions. Nature’s solution is hunger. Hunger would be on a scale of 1 to 10 as this would facilitate itself as a better multiplier than a normalized value. Once captured an animals food value is determined from it’s weight. Let’s say a zebra has a food value of 10 and a rabbit a food value of 0.25 then it would take 40 rabbits to be the equivalent of 1 zebra in food value; A lion with a hunger value of 5 taking down a zebra would bring the hunger value down to 0 as a minimum. On the other hand a lion with a hunger value of 5 taking down three rabbits in succession would then have a hunger value of 4.25. This hunger value is then used to determine how much larger the prey detection range becomes as in the real world the predators senses become more attuned as their hunger rises. The default waypoint navigation speed would gradually pick up so they could traverse their circuit range waypoints faster and with a wider and wider detection range. At the same time the hunger value, when exceeding a certain scale can also begin to affect the endurance of the predator. This could lead to a situation where a death occurs as the endurance drops to 0.000.
The Tech Demo in Age Of Survival
The first iteration of the FaunAI engine was integrated by the Team Lead, Jason, and he made a video of it for a tech demo to add to the promo materials for the game at the following link.
I will continue to add updates as I add more to the system, optimization tricks, behavioral specialties, performance characteristics and anything else that may come wandering into my head in regards to this projects ongoing development.