Menu
Lumberyard
Developer Guide (Version 1.11)

Animation Streaming

Animation is very memory-intensive and tends to use a large amount of resources. Limited memory budgets, high numbers of animated joints, and requirements for high animation quality make it wasteful for a project to keep all animations constantly loaded in memory.

Lumberyard's animation system alleviates this issue by streaming in animation resources (file granularity level) when needed, and unloading them when not needed. Streaming of asset files is achieved by using the DGLINK Streaming System. Streaming assets in and out allows the system to keep only the needed resources in memory—which is done at the expense of complexity, as you must now plan how and when animation resources are used.

Animation Data

Animation data usage is divided into two main sections:

  • The header section contains generic information for an animation (filename, duration, flags, etc).

  • The controller section contains the animation curves. For each joint involved, this section contains information on all the position and orientation values that the joint needs in order to play that animation. Even when compressed, controller data can easily take up more than 95% of the total memory required for an animation.

Animation Header Data

Header data for animations is stored in CAF files and in the animations.img file.

CAF files contain the header information on a single animation, while animations.img contains header information for all animations in the build. The animations.img is obtained as a result of processing all the animations with the Resource Compiler.

The engine usually loads all the animation files' headers from the animations.img file instead of loading from individual files (reading the information from individual files can considerably slow down loading time).

Because of the extreme size difference between controllers and headers, Lumberyard streams only the controller data in and out of memory. The header data for all animations is kept at all times in memory, as it is practical to have that information available at all times.

Note

During development—for example, when working with local animation files—you must disable usage of animations.img and load the header information from individual CAF files instead. To do so, set the ca_UseIMG_CAF console variable to 0 before the engine starts.

Animation Controller Data

The controller data for animations is stored in CAF files or DBA files.

  • CAF files contain controller information for a single animation.

  • DBA files contain controller information for a group of animations.

When a DBA is loaded, controllers for all animations contained in that DBA are available until the DBA is unloaded. For this reason, it is useful to group animations that are used together in the same DBA. An extra benefit of putting similar animations together in a DBA is that equal controllers are only stored once. This reduces the memory usage of your animations.

Loading Controller Data

The animation system properly plays animations only when their controllers are in memory.

If controller data is not available when playback of an asset is requested, the animation system streams it in from disk. Streaming of controller data is performed asynchronously—the animation system does not wait until after asset playback is requested. This prevents stalling the system.

If high level systems fail to notify the animation system that they require controller data (see the preload functions section), the animation system does not know that an asset is required until it is requested to play. This is dangerously close to when the controller data is needed. If the controller data is not available in time, it typically leads to visual glitches, which can sometimes be observed, for example, only the first time an animation is played.

Therefore, it is important to have controller data streamed in before playback of an animation is requested. This minimizes undesired glitches that occur while waiting for animation streaming to end.

The amount of time required for streaming to complete depends on many factors, such as the current system load, streaming speed of the target system, size of the resource that needs to be loaded, and so on.

Unloading Controller Data

The animation system will not unload controller data that is currently in use.

It is possible to prevent unloading of animation data entirely by setting ca_DisableAnimationUnloading to 1.

Controllers in CAF files are unloaded after the system detects that they are no longer in use. To prevent controllers in CAF files from being unloaded, set ca_UnloadAnimationCAF to 0.

Controllers in DBA files remain in memory until a certain amount of time passes after the animations in them are used. However, if the DBA is locked, controllers are not unloaded until the lock status is set back to 0.

To change the time that the animation system waits to unload controllers in DBA files, use the following cvars:

  • ca_DBAUnloadUnregisterTime – Timeout in seconds after the last usage of a controller and all animations using that DBA; when this timeout is reached, the DBA marks their controller data as 'unloaded'.

  • ca_DBAUnloadRemoveTime – Timeout in seconds after the last usage of a controller in a DBA; when this timeout is reached, the DBA performs an actual unload from memory. This value should be greater than or equal to ca_DBAUnloadUnregisterTime.

The following section describes how to lock individual resources in memory to prevent the system from unloading them.

Preloading and Keeping Controllers in Memory

Preload functions are performed by high level systems or user code (usually game code), as these contain most of the information on when and how assets are accessed. For example, trackview looks a number of seconds ahead in the timeline for any animations that appear, and calls the preload functions.

Preloading Controllers in DBA files

To preload and trigger the streaming of a DBA file:

Copy
gEnv->pCharacterManager->DBA_PreLoad(dbaFilename, priority);

To trigger the streaming of a DBA file, and request a change to the locked state (which specifies whether it should be locked in memory):

Copy
gEnv->pCharacterManager->DBA_LockStatus(dbaFilename, lockStatus, priority);

To unload all controller data in a DBA from memory (unloads data only if none of the controllers are currently being used):

Copy
gEnv->pCharacterManager->DBA_Unload(dbaFilename);

Note

To make the system automatically load and lock a DBA file while a character is loaded, use the flags="persistent" in the chrparams file.

Preloading Controllers in CAF files

To increase the reference count of a CAF file:

Copy
gEnv->pCharacterManager->CAF_AddRef(lowercaseAnimationPathCRC);

Controllers for a CAF file start streaming in when its reference count goes from 0 to 1.

To decrease the reference count of a CAF file:

Copy
gEnv->pCharacterManager->CAF_Release(lowercaseAnimationPathCRC);

Controllers for a CAF file are unloaded by the animation system only after the reference count reaches 0 (the animation system, when playing a CAF file, also increases this reference count, so that an animation is not unloaded while in use).

To check whether the controllers for a CAF file are loaded:

Copy
gEnv->pCharacterManager->CAF_IsLoaded(lowercaseAnimationPathCRC);

To synchronously load the controllers for a CAF file:

Copy
gEnv->pCharacterManager->CAF_LoadSynchronously(lowercaseAnimationPathCRC);

Synchronously loading CAF assets is strongly discouraged unless absolutely necessary, as it will likely result in stalls.