Play as the Milk Maiden in this first-person retro shooter that emphasizes mobility and an arsenal of milk-power magic. The cat with the fiddle has stolen the other gauntlet from the cow that jumped over the moon and you are all that is between the world and spilt milk!
This was my first big foray into AI programming. For Udder Chaos I built a custom state machine system that integrated systems for attacks, different forms of movement, and integrating sound with behaviors and animation.
When I wasn't building and expanding the state machine, I assisted in adding juice and other small additions to the game. Among these was working with Unity's Shuriken particle system and adding recoil/camera shake to the player camera rig.
As an extension of my responsibilities as the AI programmer I also made heavy use of Unity's animation systems. Making sure that our animations were implemented properly and would flag events correctly was the brunt of my work, but I also assisted in
This system was built in Unity so my description here will heavily use terms relating to that engine. Given the limited scope of the game, this meant we had the most control of our features so they would do exactly as we needed. However, Unity's built in AI systems were less than stellar so we built a system from scratch to best accommodate our needs. (show image of relevant in engine materials)
At its core, this system is a relatively standard state machine. However, some elements are inspired by the functionality of behavior trees. Each fixed update the core script gathers animation information from the animation graph to know whether animations are completed and whether animations have updated correctly. Then it runs whichever behavior is active and uses the results to update the animation information.
When a behavior is willing to change its state (or is forced to by outside forces), the core script can then check which behavior it should begin next. It iterates across an array of conditions until one returns true and then selects that behavior to become the active behavior. If no conditions are true, the AI will revert to whichever behavior is set as the default behavior.
This is the most straightforward element of the system. All behaviors are expected to know how to respond to particular animation tags (which I will explain next). The information from the animator may then be used during the standard function of the behavior. After this process, the behavior determines if the animation needs to change and whether it is able to be swapped with a different behavior.
Finally, the animation system has a number of tags that are used to communicate information between the AI and the Animator. The state is simply an enumerator that coincides with the index of the active behavior. Animations for behavior 1, for example, would only run during 'state 1' and allows for easier management of complex animation graphs. CompoundState is similar, but enables the behavior and animation to communicate a second level of detail regarding which animations must be played and at what times. Actions are simply tags to be used in the Unity animation timeline to cause the 'action' of a behavior to trigger (mostly for the purpose of attacks).
All in all, this was a great project. While I am proud of the system I set up here, after eventually learning the ins and outs of behavior trees I don't know if I'll look back. This experience has incentivized me to learn about behavior trees which facilitate far more dynamic behavior with many more opportunities for flexibility and scalability.