We have been hard at work on animations and we finally have something to show. Getting to this point meant processing close to 400 animation clips (so far) and importing them into the engine. This is more than double the number we were previously using.
With Unreal we used in-place animation. What this means is our code would would move the character and select an animation to play when you give the character an order. While these activities were coordinated, they didn’t directly talk to each other. As a result you often get visual artifacts such as the characters feet slipping across the ground.
We chose in-place because it was proving difficult to get root motion working with the navigation system in Unreal. With Lumberyard we introduced our own motion controller that sits between the engine’s pathfinding code and the animation system. What this new motion controller does is turn the path into a series of animations that need to be played.
So now we are generating a sequence of animations. What root motion means is each animation we play tells the engine how much the character moved that frame. Because the animation is now the source of both movement and animation the places where the character contacts the world such as their feet are much more effectively kept in sync.
Now, even this system has limits. For example when you start movement we choose between nine animations to start the movement [straight ahead, left 45,90,135,180, and right 45,90,135,180]. This means we still need to make a minor adjustment to the character's path. We also make small adjustments while the character is moving to keep them on the path. Generally these are small enough to not be noticeable.
Before we ship we will probably have close to 1000 animation clips. As you can imagine picking the right one to play in every case is really tricky. With Unreal this was managed by creating a state machine which selected which animation to play based on the state of a character. For us this proved very difficult to make robust.
Lumberyard is driven by a database of animation tags. For example a tag state for the movement animation might be “stand”, “unarmed”, “jog”. When we ask the system to play an animation of type “move” it would search the database for an animation with the matching tags. This greatly reduced the work we had to do to manage the selection process.
Now it has not been all smooth sailing. Lumberyard makes it much more time consuming to import our animation clips. As a result we have only imported the most important animations so far. The Lumberyard team are working on improving the import process, so we will return to this later, when they finish their new .FBX pipeline.
The end result is we are rapidly converging on shipping quality for the animation system. In the next development update we will talk in detail about how we do procedural map generation.