
Real-Time Character Animation with Machine Learning - An Overview of PFNN, MANN, and LMM
An in-depth look at modern machine learning-based real-time character animation technologies. We examine the PFNN, MANN, and LMM architectures, their principles and pipelines, data requirements, and network structures.
We implemented Learned Motion Matching, developed a plugin for Unreal Engine 5, and integrated trained models into a real-time animation pipeline. Next, we will review existing character animation solutions based on neural networks.
Introduction
Until recently, the standard approaches in character animation included keyframe animation or procedural animation — a family of fundamentally different methods based on inverse kinematics, ragdoll physics, or more complex systems (e.g., GTA IV — Euphoria). However, despite their widespread use, these methods have significant drawbacks: unrealistic results, high cost, limited expressiveness, reliance on manual labor, and difficulty maintaining a consistent artistic style. Then came motion matching, which delivered an entirely different level of animation quality, but only AAA-scale studios could afford such systems. Moreover, motion matching is extremely demanding on memory due to the need to store the entire animation library in RAM.
Some of these shortcomings can be naturally addressed by applying machine learning, thanks to its low memory consumption, scalability with respect to data, and ability to generalize. Today, a new shift can be observed: more and more tasks related to character movement, facial expressions, and behavior are being handed over to machine learning models. The reason is simple — games, VR/AR systems, virtual actors, and interactive simulations require not just beautiful animation, but realistic real-time behavior that adapts to the environment and user actions, which traditional systems cannot provide.
Neural networks can learn from large motion capture datasets, predict movement for upcoming frames, synthesize transitions between poses, control gait, balance, obstacle reactions, and even facial expressions synchronized with speech. The result is animation that looks natural while being generated on the fly — without pre-recorded clips. However, new capabilities come with new challenges: performance, stability, control over results, data quality requirements, and integration into existing pipelines.
In this article, I will present some of the existing machine learning-based solutions for character animation. Since the approaches discussed below are closely related to motion matching technology, I will begin with a brief overview of it.
Motion matching is a search algorithm that selects the pose from an animation database that best fits the current context. At present, this technology delivers the most responsive and plausible animations. It has been used in the following projects: The Last of Us, For Honor, Fortnite.
Instead of describing animation through a state graph, motion matching allows animators to specify pose parameters (features), and the best-matching pose is automatically selected using a nearest-neighbor search. This means that animation quality and variety depend directly on the size of the database. Since the algorithm takes poses from the database as-is, applying only blending and post-processing, the quality of the original animation is preserved, and animators retain control over the result. The motion matching process can be summarized as follows:
- Compute the desired movement trajectory
- Search the database for the most suitable pose, considering pose parameters and the movement trajectory
- Assign the closest matching pose to the character
- Post-processing
- Repeat steps 1–4
The process of adding new animation material to the database is straightforward and can be performed and debugged in real time. As a result, memory consumption grows linearly with the amount of data and the number of pose search parameters. Ultimately, the task comes down to finding a balance between result quality, memory consumption, and computational performance.

Thus, the following key disadvantages of motion matching can be identified:
- The need for a massive dataset — for example, in TLOU 2, Ellie and Abby alone have a total of 2,627 animation clips — 2 hours and 17 minutes of animations
- Lack of generativity
Typical Pipeline
The pipeline is conceptually the same for all three architectures and looks as follows:
- Preprocessing: at this stage, training data is prepared, controller parameters are automatically extracted, and terrain is matched to movement using a separate heightmap
- Training: the neural network learns to output character movement at each frame using controller parameters
- Real-time inference: input data for the neural network (controller and environment) is collected and fed into the system, which determines the character's movement
The source training data is standard motion capture, recorded as a long sequence describing various gaits and movement directions. During preprocessing, the entire sequence is mirrored to augment the dataset.
Bone position and velocity data is used in an autoregressive manner — the computed result from the previous frame is used as input for the next one.
Phase-functioned neural networks for character control (PFNN)
PFNN is a neural network architecture that operates by generating the weights of a regression network at each animation frame as a function of phase — a variable representing the movement cycle time. These weights are then used to perform regression from controller parameters at the current frame to the corresponding character pose. The proposed architecture is suitable for real-time operation thanks to its computational speed and lightweight memory footprint. Additionally, by sacrificing compactness, performance can be further improved through precomputation of the phase function.
A significant improvement in animation expressiveness is achieved through the dynamic adjustment of neural network weights based on the phase function — this approach allows the network to learn from a high-dimensional dataset where environmental geometry and human motion data are interconnected. The PFNN architecture avoids mixing data from different phases, and the regression function changes smoothly over time depending on the phase. After training, the system can automatically generate appropriate and expressive movements for a character traversing rough terrain, jumping, and avoiding obstacles — in both natural and urban environments.

The input to the neural network consists of the previous pose and controller input, while the output includes the phase change, the current character pose, and some additional parameters.
Along with the animation, controller parameters are provided as training data, consisting of the movement phase, gait semantic labels, character movement trajectory, and a heightmap along the trajectory.
- Phase labeling: performed semi-automatically. Foot contact with the surface is computed automatically via velocity and then manually corrected. Once contact data is obtained, phases are assigned: when the right foot contacts the surface, phase = 0, then the left foot = , right foot again = (). Interpolation is performed between frames.
- Gait labeling: performed manually, represented as a binary vector to disambiguate similar movement types and describe specific movement scenarios.
- Trajectory and heightmap: the root transformation of the character describing the movement trajectory is extracted. Then, along the entire trajectory and perpendicular to it on both sides, the surface height is computed.

To describe the character's state, local (relative to root transformation) bone positions and velocities at the current animation frame are used. For trajectory construction, 5 frames from the future and 6 from the past are sampled, covering a total of 1 second of past movement and 0.9 seconds of future movement. For each sample, the position and direction of the trajectory relative to the root transformation are extracted, along with a binary vector describing the gait and the surface height under and beside the trajectory at a distance of 25 cm. Thus, the full input vector for the neural network for a single animation frame is:
- — current frame
- — previous frame
- — number of sampled frames (12)
- — number of bones in the skeleton
- — trajectory positions in the 2D horizontal plane
- — trajectory directions in the 2D horizontal plane
- — heights at points to the left, right, and center of the trajectory
- — semantic labels describing the character's gait and other information
- — local bone positions
- — local bone velocities
The original paper used the following labels for :
- idle
- walking
- running
- jumping
- crouching
The output of the neural network inference is the vector:
- — number of sampled frames (12)
- — number of bones in the skeleton
- — predicted trajectory positions at the next frame
- — predicted trajectory directions at the next frame
- — local bone positions
- — local bone velocities
- — bone angles expressed in exponential map form
- — linear velocity of the root transformation along the X axis relative to the "forward" direction
- — linear velocity of the root transformation along the Z axis relative to the "forward" direction
- — angular velocity of the root transformation around the vertical axis
- — phase change
- — foot contact information (toe and heel) with the surface
The neural network consists of 3 layers:
The number of neurons in each layer is 512. The network weights are computed depending on parameters at each frame by a separate phase function . This function can be another neural network or a Gaussian process, but the paper proposes using a cyclic cubic Catmull-Rom spline with 4 control points. This approach means that each control point represents a specific configuration of network weights , and the function performs smooth interpolation between these configurations.
Training the neural network amounts to solving the optimization problem for the phase function parameters . The following loss function is used:
- — mean squared error
- — regularization introduced to prevent the weights from becoming too large ()
Adam was chosen as the optimizer.
In real time, at each animation frame, the phase and vector are fed as input to the neural network. The velocity and direction of movement received from the controller for each future frame are blended with the data predicted by the neural network at the previous frame using the following formula:
- — additional bias controlling the character's responsiveness
Mode-adaptive neural networks for quadruped motion control (MANN)
This work extends the PFNN architecture to the animation of quadruped characters. Due to fundamental differences in movement patterns, it is impossible to define a single phase for all four limbs when the gait changes. Manual labeling of an unstructured dataset also becomes impractical. Therefore, the phase function is replaced by an additional neural network. The resulting system includes a motion prediction network and an expert selection network (gating network — similar to the mixture of experts architecture): while the first network predicts the character's state based on the previous frame's state and controller input, the second network dynamically updates the weights of the first network by selecting and mixing a new entity called "expert weights," each of which corresponds to a specific movement pattern. This architecture allows the networks to learn from data without labeled gaits, completely eliminating the phase labeling stage.
Movement classification is performed manually to identify 6 movement classes: locomotion, sitting, standing, waiting, lying down, and jumping. This is done so that in real time the user can specify the movement class via the controller.
The paper examines four gait types: walk, pace, trot, and gallop. Although the system does not require these labels for real-time character control, an analysis of the distribution of these types in the dataset is performed based on velocity calculations.
Input and output data are generally similar to PFNN: 5 future frames and 6 past frames are also sampled, the character's root transformation and movement direction are computed.
The input data vector:
- — current frame
- — previous frame
- — number of sampled frames (12)
- — number of bones
- — trajectory positions in the 2D horizontal plane
- — trajectory directions in the 2D horizontal plane
- — velocities at trajectory points in the 2D horizontal plane
- — desired velocity at trajectory points
- — one-hot vector of movement classes at trajectory points
- — local bone positions
- — local bone rotations
- — local bone velocities
Adding bone rotations to the input vector allowed for more responsive animation.
The output of the neural network inference is the vector:
- — current frame
- — next frame
- — number of sampled frames (12)
- — number of bones
- — trajectory positions
- — trajectory directions
- — velocities at trajectory points
- — local bone positions
- — local bone rotations
- — local bone velocities
- — linear velocity of the root transformation along the X axis
- — linear velocity of the root transformation along the Z axis
- — angular velocity of the root transformation in the 2D horizontal plane
Bone rotations are represented as relative "up" and "forward" vectors to avoid quaternion interpolation issues during neural network training.

The motion prediction network architecture is similar to PFNN, but the weights are computed by mixing expert weights ,
where . is a tunable meta-parameter depending on the complexity and size of the training data. are the mixing coefficients computed by the gating network.
The gating network architecture consists of 3 layers:
- — a subset of including foot bone velocities, current movement classes, and the desired character velocity.
- — softmax function for normalizing inputs so that their sum equals 1, which is necessary for subsequent linear mixing
The network parameters are defined as follows:
- — number of neurons in hidden layers (32)
Training the network amounts to finding for the corresponding , which is a standard regression task. The following loss function is used (MSE between prediction and ground truth):
AdamWR was chosen as the optimizer.
Learned motion matching (LMM)
LMM is based on Ubisoft's own implementation of motion matching. Classic motion matching consists of 3 stages: Projection, Stepping, Decompression — for each of which a trained neural network is proposed as an alternative.

For the locomotion scenario, a 27-element vector per animation frame is proposed as pose parameters:
- — trajectory positions in 2D projected onto the surface at 20, 40, 60 frames in the future (at 60 FPS)
- — trajectory direction at 20, 40, 60 frames in the future
- — local positions of foot bones
- — linear velocities of foot bones
- — linear velocity of the hip bone
Next, a vector containing all pose information for each animation frame is defined:
- — local bone positions
- — local bone rotations in axis-angle representation
- — linear bone velocities
- — angular bone velocities
- — linear velocities of root transformation
- — angular velocities of root transformation
- — task-specific additional data (e.g., foot contact information)
These vectors are computed for each frame, combined into matrices , called the matching database and animation database respectively, and used in the training algorithm. In real time, every N frames or when the controller input changes significantly, a query vector is constructed — analogous to the pose parameter vector — and fed as input to the Projection stage. Once a new frame is found, animation playback starts from it and a transition is inserted.
- Projection: nearest-neighbor search to find the pose parameter vector in that best matches .
- Stepping: advances the index in the matching database.
- Decompression: retrieves the pose from the animation database corresponding to the current index in the matching database.
By replacing each of these stages with a neural network, the need to store the matching database and animation database in memory is eliminated. To this end, 4 neural networks are introduced:
- Decompressor: eliminates the need to store in memory, takes and a latent vector as input
- Compressor: acts as an encoder for finding by compressing into a lower-dimensional vector
- Stepper: together with the projector, eliminates the need to store in memory; learns the dynamics of the system by computing changes in and values to obtain and for the next frame
- Projector: emulates the nearest-neighbor search, takes as input and predicts the closest and
By combining these 4 neural networks, the result is learned motion matching, shown in the figure below.

Since the pose parameter vector typically does not contain enough information to derive the corresponding pose, a latent space is introduced. Its values are obtained through the Compressor network — a mapping from to the corresponding . This vector is then concatenated with and fed into the Decompressor, which attempts to reconstruct the original pose . In this way, the network discovers what information is missing from the pose parameter vector and encodes it in .
A key aspect of Decompressor training is the loss function designed to minimize the visual perception of error, which uses forward kinematics to evaluate the error in character space. Velocity-aware loss terms are also added so that the result changes smoothly over time.
Pseudocode for Compressor (C) + Decompressor (D) training algorithm
end
After training, the Compressor network is not required for real-time operation, since it is only needed to compute used for training the other networks.
The Stepper network is trained to take vectors and of the current frame as input and output a delta added to them to obtain vectors and for the next frame. A small window of and vectors is taken, and the next values of pose parameters and latent variables are predicted and fed to the next frame.
Pseudocode for Stepper (S) training algorithm
end
Finally, the Projector network completely eliminates the need to store and in memory. For its training, a vector is taken, Gaussian noise is sampled and scaled by random noise , the resulting value is added to to obtain , and the nearest is found via nearest-neighbor search. The Projector is then trained to output the corresponding pose parameter vectors and latent variables .
Pseudocode for Projector (P) training algorithm
end
By sampling noise of varying magnitude, the Projector is made robust to perturbations at different scales.
For all loss functions in all training algorithms, the coefficients are chosen to equalize the initial values (at the 1st training iteration).
RAdam was chosen as the optimizer.
The number of layers, neurons, and activation functions for the networks are shown in the figure below:

The runtime operation of the architecture proceeds as follows:
- is formed and fed as input to the Projector, which outputs and
- The found and are fed as input to the Stepper, which advances them in time
- The result from step 2 is fed as input to the Decompressor, which outputs the final character pose
Platform limitations prevent embedding a demonstration here; video materials can be found via the original sources.
Conclusion
This article did not include performance and quality evaluations of the discussed approaches — you can find those in the original papers in more detail.
Additionally, some important components (trajectory construction, character-to-heightmap matching) were not covered as they fall outside the scope of this article. In the next article, I plan to cover some of the omitted details.
References: