Skip to main content

Migrating from V0 to V1

AnimatorAsCode V1 introduces the following main breaking changes:

  • VRChat Avatars is now an optional dependency. AnimatorAsCode can now be used in non-VRChat projects.
    • All VRChat-related functions have been split between two classes of extension methods.
  • You are now encouraged to use a non-destructive workflow by generating an animator controller asset without relying on an existing animator controller asset.
    • VRChat methods that use a destructive workflow, such as AacFlBase.CreateMainFxLayer() are located on their own class of extension methods.
  • There are a few fixes in the inconsistency in the API, such as making fields and constructors private, and turning fields into properties with getters.

Assembly definition

If you use assembly definitions, change the assembly reference from AnimatorAsCodeFramework to the following:

  • AnimatorAsCode.V1 in all cases.
  • AnimatorAsCode.V1.VRChat if you depend on VRChat.
  • AnimatorAsCode.V1.VRChatDestructiveWorkflow also if you need to edit the playable layers of the avatar directly.
    • Consider switching to a non-destructive workflow using VRCFury or Modular Avatar! See below.

Code changes

Code

  • Change AacV0 to AacV1
  • Change using AnimatorAsCode.V0; to using AnimatorAsCode.V1;
  • Change AacFlSettingObjectReferenceKeyframes to AacFlSettingKeyframesObjectReference
  • Change TrackingElement to AacAv3.Av3TrackingElement
  • If your project depends on VRChat, you will need to use extension methods.
    • Add using AnimatorAsCode.V1.VRC; in your class imports to use the VRChat extension methods.
      • The extension methods are contained within the class AnimatorAsCode.V1.VRC.AacVRCExtensions.
    • Add using AnimatorAsCode.V1.VRCDestructiveWorkflow; in your class imports to use the VRChat destructive workflow extension methods.
      • The extension methods are contained within the class AnimatorAsCode.V1.VRCDestructiveWorkflow.AacVRCDestructiveWorkflowExtensions
  • (Optional) Change MotionTime( to WithMotionTime(
  • (Optional) Change WithKeyframes( to WithUnit(
  • There are other code changes, see AacConfiguration section right below.

Code with no equivalences

It is no longer possible to instantiate some of the internal classes.

AacConfiguration

VRCAvatarDescriptor is only needed for destructive workflows

Since AacConfiguration no longer contains the avatar descriptor, you will need to use the extension method AacConfiguration.WithAvatarDescriptor(VRCAvatarDescriptor) to define the avatar in the configuration.

If you decide to migrate your scripts to a non-destructive workflow, this step is not necessary: You can remove the avatar descriptor from the configuration.

For example:

using AnimatorAsCode.V1;
using AnimatorAsCode.V1.VRCDestructiveWorkflow;
// ...

AacV1.Create(new AacConfiguration
{
SystemName = systemName,
AnimatorRoot = avatar.transform,
DefaultValueRoot = avatar.transform,
AssetContainer = assetContainer,
AssetKey = assetKey,
DefaultsProvider = new AacDefaultsProvider(writeDefaults: options.WriteDefaults)
}.WithAvatarDescriptor(avatar)); // The avatar descriptor is now defined by invoking an extension method.

New configuration field: ContainerMode

The configuration has a new field: ContainerMode.

ContainerMode dictates how assets should be stored in the asset container.

If you use a non-destructive workflow with NDMF, AAC usually does not need to store anything inside the asset container, because NDMF takes care of it; except for Animator Controllers.

It is necessary to persist the Animator Controller as soon as it is created so that we may create states containing behaviours inside of them.

  • If you use a non-destructive workflow, use ContainerMode = AacConfiguration.Container.OnlyWhenPersistenceRequired
  • If you use a destructive workflow, use ContainerMode = AacConfiguration.Container.Everything

Using Animator As Code in non-destructive workflows

Go to the Getting started page for an example on how to create a non-destructive plugin for NDMF.

Miscellaneous contract changes

  • AacFlLayer, AacFlClip, and AacFlEditClip are now classes instead of structs.
  • Some public fields that used to be settable by accident have been changed into non-settable public properties with a getter (this does not include AacConfiguration).
  • Some read-only public fields have been changed into public properties with a getter.
  • Many constructors of classes have been made private, as they are meant to be instantiated only through invocations of other functions.
  • AacFlFloatParameterGroup.ToList() now correctly returns the List<AacFlFloatParameter> instead of List<AacFlBoolParameter>.
  • AacFlIntParameterGroup.ToList() now correctly returns the List<AacFlIntParameter> instead of List<AacFlBoolParameter>.
  • Some functions that accept Component[] used to throw an error if an element in the array was null. They will no longer throw errors.