Fix CMC Traversal Animation Selection
Today I investigated a traversal animation issue in the Game Animation Sample 5.8 CMC character used by Pisces.
When the character stood on a 2.5m platform and tried to traverse over a 1m obstacle with no floor behind it, its hands grabbed the air above the ledge. Running traversal worked correctly, but stationary traversal did not.
How CMC selects a traversal animation
The traversal flow is:
- The
CharacterMovementComponentprovides the character’s movement mode, such asWalking,Falling, orFlying. - The character implements
Get Properties for TraversalfromBPI_SandboxCharacterPawn. This converts the CMC movement mode into a custom traversal movement mode, stored inS_CharacterPropertiesForTraversal. AC_TraversalLogic::TryTraversalActionreads those properties and checks the obstacle geometry to determine the traversal action, obstacle height, and other conditions.CHT_TraversalMontages_CMCuses the action type, traversal movement mode, obstacle height, speed, and pose matching to select a montage and start time.PerformTraversalAction_CMCplays the montage and temporarily sets the CMC movement mode toFlying. When the traversal finishes, it restores an appropriate movement mode.
The CMC movement mode is mapped to the traversal movement mode as follows:
| CMC movement mode | Traversal movement mode |
|---|---|
| None | OnGround |
| Walking | OnGround |
| Navmesh Walking | OnGround |
| Falling | InAir |
| Swimming | InAir |
| Flying | InAir |
| Custom | InAir |
For example, when the obstacle has no back floor, the traversal action can be Vault. For the same action and obstacle height, the Chooser can select different animations depending on the traversal movement mode:
OnGroundcan select a grounded vault montage such asVault_1_0_stand_F_Lfoot.InAircan selectCatch_Vault_high.
What went wrong
The obstacle height was correctly measured at about 97.5cm, and the FrontLedge motion-warping target appeared to be in the correct position. However, the character ended up playing Catch_Vault_high, which made its hands grab above the ledge.
I tried forcing Catch_Hurdle_med_stand, which fixed the hand alignment. This suggested that the problem was related to animation selection rather than simply the ledge position.
Further debugging showed that TryTraversalAction could run again while a traversal was already in progress. During a traversal, CMC is intentionally set to Flying, which is reported to the Chooser as InAir. A repeated traversal check could therefore select an airborne catch animation instead of the original grounded vault animation.
The fix
I added a guard at the start of TryTraversalAction:
// Pseudocode for the Blueprint logic.
if (DoingTraversalAction)
{
return;
}
This prevents a new traversal request from being processed while the character is already traversing.
After the fix, the correct stationary vault animation played and the character aligned with the ledge in testing.