☀️ Animator As Code V1
I am releasing Animator As Code V1.
Starting from V1.1.0, all Animator As Code V1 packages are leaving Alpha/Beta.
Animator As Code V1 can now be safely used in public projects that wish to do so.
Compatibility with projects that contain Animator As Code V0
Animator As Code V1 is designed to be installed even in projects that already have Animator As Code V0.
Animator As Code V0 will not be overwritten by Animator As Code V1. Both installations will act as separate, non-conflicting installs. Projects like FaceEmo will continue to function properly.
In fact Animator As Code V1 has already been extensively used in my own tools (Prefabulous, ComboGestureExpressions, Vixen).
There is no real need to migrate between V0 and V1, if V0 already provides all the functionality you need in your project.
If you choose to migrate, V0 and V1 are almost identical.
Features in V1 compared to V0
Sub-State Machines
- Pull major contributions from @galister which:
- Adds support for sub-state machines, which is important because it enables the creation of states that evaluate multiple transitions within one frame,
which is not possible to do without sub-state machines (with one exception).
- This trait is already extensively used in ComboGestureExpressions V2 and above.
- Share functionality of state and sub-state machines.
- Share functionality of Int and Float parameters together.
- Adds support for sub-state machines, which is important because it enables the creation of states that evaluate multiple transitions within one frame,
which is not possible to do without sub-state machines (with one exception).
// When using Sub-State Machines, the Sub-State Machine will evaluate all transitions until
// it resolves a destination state within one single frame.
// This means it can traverse multiple transition conditions at once, no matter how nested
// the Sub-State Machine is.
//
// This is not doable with just states, so Sub-State Machines have a functional value beyond mere organization.
var a = layer.IntParameter("IntA");
var b = layer.IntParameter("IntB");
var rootSsm = layer.NewSubStateMachine("UsingNestedSubStateMachines");
for (var i = 0; i < 16; i++)
{
// A Sub-State Machine can have other Sub-State Machines created inside them.
// TransitionsFromEntry creates a transition between `subSsm` and the Entry node of the Sub-State Machine it belongs in.
// Exits creates a transition between `subSsm` and the Exit node.
var subSsm = rootSsm.NewSubStateMachine($"A = {i}");
subSsm.TransitionsFromEntry().When(a.IsEqualTo(i));
subSsm.Exits();
for (var j = 0; j < 16; j++)
{
var state = subSsm.NewState($"A = {i} and B = {j}");
state.TransitionsFromEntry().When(b.IsEqualTo(j));
state.Exits()
.When(a.IsNotEqualTo(i))
.Or()
.When(b.IsNotEqualTo(j));
}
}
// This creates a transition between the Sub-State Machine and itself.
// When that Sub-State Machine exits, it will re-enter itself.
rootSsm.Restarts();
Packaging, Non-VRChat projects, and non-destructive
- Make it usable in non-VRChat avatar projects.
- VRChat-related functionality is now exposed as extension functions in a separate package.
- Also, separate destructive functions and non-destructive functions.
- Since this no longer requires a VRChat project, this also means it may now be usable in VRChat world projects.
// Animator As Code V1 no longer requires VRChat (compared to V0).
// VRChat-specific functions have been moved to extension methods.
// If you want to use VRChat Avatars functionality, add the `Animator As Code V1 - VRChat` package, and do the following:
//
// Add the following import, which contains extension methods:
using AnimatorAsCode.V1.VRC;
// To access VRChat parameters, use the following extension method:
var vrcAv3 = layer.Av3();
// To access VRChat assets, use the following extension method:
var vrcAssets = aac.VrcAssets();
layer.NewState("UsingVRChat")
.WithAnimation(vrcAssets.ProxyForGesture(AacAv3.Av3Gesture.HandOpen, false))
// VRChat State Behaviours are created through extension methods located in namespace `AnimatorAsCode.V1.VRC`
.TrackingAnimates(AacAv3.Av3TrackingElement.RightHand)
.Driving(driver => driver.Sets(layer.BoolParameter("A"), true))
.TransitionsFromEntry()
.When(vrcAv3.GestureRight.IsEqualTo(AacAv3.Av3Gesture.HandOpen));
- Make it more usable in non-destructive components.
- It is already in use in Prefabulous and Vixen.
- Move to packages, for distribution using VCC (and now, ALCOM).