Animancer v4.0

Released 2020-01-28

When upgrading to a newer version of Animancer, you must delete any previous version from your project first.

Highlights

  • The main public API has been entirely restructured:
    • The Play, CrossFade, CrossFadeFromStart, and Transition methods have all been unified as Play with fewer overall parameter combinations.
    • Layers are now treated as a proper collection. So instead of animancer.LayerCount, animancer.GetLayer(...), or animancer.SetLayerAdditive(...), you now use animancer.Layers.Count, animancer.Layers[...], or animancer.Layers.SetAdditive(...).
    • Same for states. So instead of animancer.GetState(...) you now use animancer.States[...] and animancer.CurrentState is now animancer.States.Current.
    • Serializables are now called Transitions (i.e. you now use ClipTransition instead of ClipState.Serializable).
  • [Pro-Only] New Animancer Event system for general events without needing to use Unity's Animation Events:
    • You can specify events per-state instead of per-clip.
    • You can add events and set callback delegates directly in code without needing to hook up magic strings to public methods.
    • The AnimancerState.OnEnd callback has moved to AnimancerState.Events.OnEnd and you can optionally specify a time for it instead of always being at the end of the clip.
  • New Transition Preview Window allows you to preview your transitions on your character without entering Play Mode.
  • Implemented Mixer Time Synchronization.
  • New PlayableAssetState allows you to play Timeline assets in Animancer.
  • All transition types now have a corresponding Transition Asset type.
  • Added support for Unity 2019.3 (most upgrades are fine, but that one broke a lot of things).
  • Added Weapons example as well as instructions for downloading animations from Mixamo and configure their Import settings.
  • Added a C# in Unity section to explain the fundamentals of programming in Unity for beginners. #7

Upgrade Guide

The main public API has been significantly restructured in several ways which will affect all users, so this section will help you fix the errors you get when upgrading a project from an earlier version.

Remember to always delete any older version of Animancer before upgrading.

Serialized Data

Some of the changes to serialized data structures will unfortunately cause certain values to be lost when upgrading so if you were using any of the following things you will need to set them again manually:

  • The AnimancerComponent.StopOnDisable bool was previously serialized by the Animator component itself, but it has now been replaced by the AnimancerComponent.DisableAction enum which is serialized in the AnimancerComponent itself (and accessable via the ActionOnDisable property). Stop and Pause correspond to the previous true and false, but there are now several other values too.
  • ClipTransition.StartTime (formerly ClipState.Serializable.StartTime) is now always serialized as a normalized time value since the Inspector shows the value as both normalized time and seconds. So if you previously had the value set to seconds, it will now be incorrect.
  • Mixer Time Synchronization is now enabled by default for all mixers so they will give different results to before it was implemented (likely better results).

Playing and Fading

The AnimancerComponent.Play, CrossFade, CrossFadeFromStart, and Transition methods are now all called Play. The Playing Animations page explains their differences.

In v3.1, AnimancerComponent had several overloads each of Play/CrossFade/Transition which were made even more complicated by the presence of default parameters for fadeDuration and layerIndex:

// Old Methods from v3.1:

Play(AnimationClip clip, int layerIndex = 0)
Play(AnimancerState state)
Play(object key)

// Note: replaced "DefaultFadeDuration" with just "Default" to fit everything on one line.
CrossFade(AnimationClip clip,            float fadeDuration = Default, int layerIndex = 0)
CrossFade(AnimancerState state,          float fadeDuration = Default)
CrossFade(object key,                    float fadeDuration = Default)
CrossFadeFromStart(AnimationClip clip,   float fadeDuration = Default, int layerIndex = 0)
CrossFadeFromStart(AnimancerState state, float fadeDuration = Default, int layerIndex = 0)
CrossFadeFromStart(object key,           float fadeDuration = Default, int layerIndex = 0)

Transition(ITransition transition, int layerIndex = 0)

The various default parameters meant that those methods had a total of 22 parameter combinations, making them rather unwieldy and confusing for new users.

This has been improved in several ways by v4.0:

  • All of those methods are now called Play.
  • The Collections change allowed the layerIndex parameter to be removed (so Play(clip, 1) is now Layers[1].Play(clip)).
  • The new FadeMode enum controls how a fade actually works, which includes the old CrossFadeFromStart functionality and the ability to use the specified fadeDuration as a portion of the clip length rather than raw seconds. See the FadeMode API documentation for the details of each value.
  • This takes it down to only 12 parameter combinations:
// New Methods in v4.0:

// Play.
Play(AnimationClip clip)
Play(AnimancerState state)
Play(object key)

// CrossFade and CrossFadeFromStart.
Play(AnimationClip clip,              float fadeDuration, FadeMode mode = FadeMode.FixedSpeed)
Play(AnimancerState state,            float fadeDuration, FadeMode mode = FadeMode.FixedSpeed)
Play(object key,                      float fadeDuration, FadeMode mode = FadeMode.FixedSpeed)

// Transition.
Play(ITransition transition)
// New method allows you to override the fade details of the transition.
Play(ITransition transition, float fadeDuration, FadeMode mode = FadeMode.FixedSpeed)

Unfortunately this means it is no longer possible to have a default value for the fadeDuration parameter because skipping that parameter would just use the instant Play(clip) method instead of Play(clip, defaultFadeDuration). The AnimancerPlayable.DefaultFadeDuration constant still exists though, since it is used in several places such as the default value to use for a ClipTransition. Also note that the value is now 0.25 seconds to match the default Mecanim transition settings (it used to be 0.3 as the default used by the Legacy animation system).

Collections

All Layer functionality in AnimancerComponent has been moved into the new Layers property.
Old (v3.1) New (v4.0)
animancer.Play(clip, 1) animancer.Layers[1].Play(clip)
animancer.LayerCount animancer.Layers.Count
animancer.GetLayer(1) animancer.Layers[1]
animancer.SetLayerAdditive(1, true) animancer.Layers.SetAdditive(1, true)
animancer.Layers[1].IsAdditive = true
animancer.SetLayerMask(1, mask) animancer.Layers.SetMask(mask)
animancer.Layers[1].SetMask(mask)
AnimancerPlayable.maxLayerCount = 8 AnimancerPlayable.LayerList.defaultCapacity = 8
AnimancerPlayable.LayerList.SetMinDefaultCapacity(8)

In earlier versions the AnimancerComponent class was the only one with access to its GetKey(AnimationClip) method, meaning that it could have a Play(AnimationClip) method where other classes (AnimancerPlayable and AnimancerLayer) could not because they would not be able to determine what key to look up the state with in the internal dictionary (usually the clip is its own key, but NamedAnimancerComponent uses the clip's name so you can call Play("Name")). But Animancer v4.0 gives the AnimancerPlayable a reference to its component, so now you can call animancer.Layers[1].Play(clip) as shown above. Also note that this changes the meaning of the default animancer.Play(clip) so that instead of playing the animation on layer 0 it will now leave it on whatever layer it is currently on.

All State functionality in AnimancerComponent has been moved into the new States property.
Old (v3.1) New (v4.0)
animancer.CurrentState animancer.States.Current
animancer.StateCount animancer.States.Count
animancer.CreateState(clip) animancer.Layers[0].CreateState(clip)
animancer.GetState(clip)
animancer.GetState("Name")
animancer.States[clip]
animancer.States["Name"]
animancer.GetOrCreateState(clip) animancer.States.GetOrCreate(clip)
animancer.Dispose(clip) animancer.States.Destroy(clip)

Renaming

Old Name (v3.1) New Name (v4.0) and Reason
All Serializable classes such as ClipState.Serializable Transition
A more descriptive name. They encapsulate the fade duration, start time, etc. of an animation in much the same way as transitions in an Animator Controller. The fact that they are serializable is less significant.
IAnimancerTransition
IAnimancerTransitionDetailed
ITransition
ITransitionDetailed
They are in the Animancer namespace anyway.
FloatControllerState
Vector2ControllerState
Vector3ControllerState
Float1ControllerState
Float2ControllerState
Float3ControllerState
They each wrap a specific number of float parameters, even if they happen to also allow those parameters to be accessed as a Vector2 or Vector3.
Most Dispose methods Destroy
Removed IDisposable from everything that does not follow regular disposal patterns. It makes no sense to put an AnimancerState in a using statement and if you declare a new ClipState locally, you do not need to dispose it because it will be cleaned up when the graph is destroyed.
All of the AnimancerPlayable.StateDictionary.Destroy methods that take collections AnimancerPlayable.StateDictionary.DestroyAll
To avoid ambiguity.
AnimancerNode.PortIndex AnimancerNode.Index
A simpler name since referring to "ports" was just confusing people anyway.
AnimancerLayer.CurrentStateID
AnimancerPlayable.CurrentStateID
AnimancerLayer.CommandCount
AnimancerPlayable.CommandCount
A more descriptive name.
IEarlyUpdate IUpdatable
Now contains both EarlyUpdate and LateUpdate methods.
MixerState.AreWeightsDirty MixerState.WeightsAreDirty
Better phrasing.

Features

Improved Transition Inspector

As mentioned above, AnimancerState.Serializable and all its derived classes have been renamed to Transition (see Transitions for details). But that's not all, they have also received a major upgrade to their Inspector interface:

Old (v3.1) New (v4.0)
[SerializeField]
private ClipState.Serializable _Walk;
[SerializeField]
private ClipTransition _Walk;

There are quite a few improvements here:

  • The "eye" button in the top right opens a new window for previewing the transition.
  • Rather than giving the Start Time a Normalized toggle to swap between normalized time and raw seconds, it now simply shows both values side by side so you can edit whichever one you want. This has been applied to the other fields as well.
  • All relevant fields now display an appropriate suffix to indicate the units ("x" indicates normalized time while "s" indicates raw seconds).
  • Speed now has a toggle to determine if it is actually applied (otherwise the state simply retains whatever speed it had previously).
  • The new Animancer Event system allows the OnEnd callback to have a custom time instead of always being at the exact end of the animation, so that value is made available in the Inspector with a toggle to show a UnityEvent that lets you configure the callback as well.
    • Note that when the End Time toggle is disabled, the value will actually be calculated based on the Speed. When playing forwards the animation will end at NormalizedTime == 1, but when playing backwards it will end at NormalizedTime == 0.
  • Down the bottom is a visual timeline display of the main parameters:
    • The labels show key times (in seconds, rounded off).
    • The blue highlighted area represents the fading in and out.
    • The grey bar down the bottom represents the actual length of the animation.
    • The button on the right adds an Animancer Event which will also be shown in this area.

There are also a few changes on the code side:

  • Removed StartTimeIsNormalized and renamed StartTime to NormalizedStartTime. It always saves the normalized time value regardless of which one you set in the Inspector.
  • Speed can now be set to NaN to prevent it from changing the existing value (this is what disabling the Inspector toggle does to any of the fields).

Transition Previews

The "eye" button in the top right of each Transition in the Inspector opens a window for previewing the transition so you can fine tune its details and see what your model looks like without needing to enter Play Mode.

Transition Assets

All transition types now have a corresponding Transition Asset (a ScriptableObject with a single field for that transition type):

  • AnimancerTransition is now the non-generic base class for transition assets.
  • Added transition assets for all transition types using the naming convention that XXXTransition has a XXXTransition (which will create a XXXState when played). For example, a ClipTransition holds a ClipTransition.
  • Any references to AnimancerTransition from previous versions are equivalent to the new ClipTransition, however you may wish to leave fields as they are so that any transition asset can be assigned if you aren't doing anything specific to ClipTransitions. Any previously created assets will be automatically changed to the new type.
  • AnimancerTransition no longer exposes the properties of the Transition (except for those required by ITransition) so instead of transitionAsset.Clip you now need to use transitionAsset.Transition.Clip. This greatly simplifies its implementation as well as the implementation of all derived classes and makes it clearer that modifications are being applied to an object which may be shared.
  • AnimancerTransition.Transition now has a comment warning that the transition.State can only hold one value even though multiple states could have been created on different objects from that same transition.

Animancer Events

Animancer has always supported Unity's inbuilt Animation Events, but they have several notable drawbacks which are avoided by the new event system:

  • The Events page explains the differences between the two systems.
  • Animancer Events are primarily configured in the Inspector as part of Transitions to make use of the new Transition Preview system:

  • They can also be configured in code:
// MeleeAttack.cs:

[SerializeField] private ClipTransition _Animation;

protected virtual void Awake()
{
    // Make sure it has the expected number of events.
    Debug.Assert(_Animation.Events.Count == 2, "Expected 2 events for the hit start and end");

    // AnimancerEvent.Sequence always sorts itself so we know the start will be before the end.
    _Animation.Events.Set(0, OnHitStart);// Set the callback for event 0.
    _Animation.Events.Set(1, OnHitEnd);// Set the callback for event 1.

    _Animation.Events.OnEnd = Character.EnterIdleState;
}

public void Attack()
{
    Character.Animancer.Play(_Animation);
}
  • Every event sequence has a separate End Event which takes the place of the old AnimancerState.OnEnd callback and allows a custom time to be specified instead of always occuring at the very end of the animation.
  • End Events are included in Animancer Lite, but the ability to set a custom end time and use other events is only available in the Unity Editor unless you purchase Animancer Pro.
  • As with End Events prior to Animancer v4.0, all events are cleared (and returned to the ObjectPool) whenever a new animation is played. See Clear Automatically for details.
  • By default, this system uses UnityEvents to define the event callbacks in the Inspector. However, it can be modified to use any other similar type of events. In particular, changing it to use UltEvents only takes a few simple steps.

Mixer Time Synchronization

  • Mixer States can now synchronise the times of their children.
    • It's not quite as advanced as the proper Foot Phase Synchronization used in Blend Trees which analyses the strides the character makes so that it can better synchronise animations with non-uniform timings such as when walking with a limp or an animation that includes multiple walk cycles.
    • But it does have one major advantage: you actually get to control it so you can choose which animations are synchronised.
    • It's on by default and can be disabled for individual children using the SynchroniseChildren array.
    • This advantage can be seen in the Linear Mixers example. Enabling synchronization on all animations gives the same result as the Blend Tree, meaning that the blending between Idle and Walk gives a much slower shuffle than it should. But disabling synchronization on the Idle gives a much better result because there's no need for consistency between the timing of those two animations.
  • MixerState.IsLooping now returns true if any child state is looping.

Timeline

  • Added PlayableAssetState for playing PlayableAssets.
  • Added an introduction sequence to the Platformer example. This allows the sequence of animations to be configured using the Timeline window and then played as if it were a single animation.

Changes

  • Replaced AnimancerComponent.StopOnDisable with ActionOnDisable which is a AnimancerComponent.DisableAction enum with Stop and Pause corresponding to the previous true and false as well as several new values.
  • AnimancerTransition.State is now the state most recently passed into Apply (backed by the un-cast BaseState) so they can be more easily used on multiple objects.
    • Overrides of CreateState no longer need to manually set the State.
  • Changed HybridAnimancerController.PlayController to return its ControllerState.
  • ControllerTransition now uses itself as the key instead of the controller in case something else happens to use the same controller with a different set of parameters.
  • AnimancerLayer.CreateState now properly sets the AnimancerState.Key.
  • Added a Validate class for all the validation methods and Lite restrictions.
    • Validate.FadeDuration now allows 0 in Animancer Lite.
    • All general validation is now conditional based on the UNITY_ASSERTIONS symbol (in the Unity Editor, Development Builds, and Animancer Lite).
  • Changed AnimancerState.IsPlayingAndNotEnding to not try to look ahead one frame because it was only using the delta time from the previous frame so it was unreliable at best and wouldn't even be using the right type of delta time for AnimatePhysics or UnscaledTime. But it does now account for the new End Event time.
  • Changed the Inspector display of "Dirty Early Nodes" to "Updatables".
  • Moved AnimancerNode.IsPlaying to AnimancerState since layers do not need it.
  • Added AnimancerState.NewTime which only gets called when the Time is actually changed and is virtual.
    • Added a minor optimisation in the setter to only cast the value to double once.
    • Moved time caching from ClipState to the base AnimancerState so it can be used by all states.
    • Added a non-NaN assertion to the AnimancerState.Time setter.
    • ManualMixerState overrides NewTime to access the weighted average Time of all child states.
    • ControllerState overrides NewTime to access the StateInfo.normalizedTime.
  • Removed AnimancerState.NormalizedSpeed because it was not really that useful and got in the way of auto-correct suggesting NormalizedTime. The getter was simply Speed / Length and the setter Speed = value * Length.
  • Refactored the system for checking if an AnimationClip has an Animation Event with a particular name:
  • Changed StateBehaviour.Reset to OnValidate so it always enforces its rule.
  • Replaced the custom transition context menus with the standard serialized property context menu:
    • It now displays the size of the serialized Animancer Event arrays.
  • Made several AnimancerState members virtual instead of abstract: AverageVelocity, ApplyAnimatorIK, ApplyFootIK.
  • Added Assembly Definitions for Animancer.FSM and Animancer.Examples to make sure the FSM system is entirely separate.
  • Removed null checks from AnimancerPlayable.Play(animator, playable, component) so it will now throw exceptions if the parameters are null.
  • BoolPref can now take a custom key prefix.
    • Added prefixes to all prefs.

Improvements

  • AnimancerComponent.InitializePlayable will now try using GetComponent if it has no Animator reference and throw an exception if one still isn't found.
  • NamedAnimancerComponent now avoids initializing its AnimancerPlayable in Awake if it has no animations.
  • Improved the output setup of AnimancerPlayable:
    • Removed the exception for initializing without an Animator.
    • Renamed the static Play methods to SetOutput and made them non-static.
    • Calling SetOutput multiple times will now destroy the old PlayableOutput so it does not cause errors in Unity 2019.3+ and you can change the Animator properly.
  • Improved ITransition:
    • It now implements a FadeMode directly instead of bool CrossFadeFromStart.
    • Play(transition) no longer tries to calculate the fade out duration. If you want to do that, you need to call AnimancePlayable.GetFadeOutDuration and pass it into Play(transition, duration, mode).
    • Moved the main part of AnimancerPlayable.GetFadeOutDuration to AnimancerEvent, leaving behind only the part specific to Animation Events with the function name "End".
  • ClipTransition.Apply now applies a default start time based on the speed if the state.Weight == 0. Same for PlayableAssetState transitions.
  • AnimancerState.NormalizedTime now returns 0 if Length is 0.
  • AnimancerState.Duration now sets the speed to infinity if the value is set to 0.
  • The AnimancerNode.Speed and Weight setters now assert that the value is not NaN.
  • Added Restore Bind Pose context menu function to Animator components.
  • The "Threshold" header in the Mixer Inspector is now a dropdown menu which lists all the threshold calculation functions. #12
  • Adding a HybridAnimancerComponent to an object with an AnimatorController assigned to its Animator will now assign that controller to the animancer instead of only clearing it.
  • Removed unnecessary calls to SetInputCount and SetInputWeight during AnimancerPlayable.OnPlayableCreate.
  • Minor optimisation in AnimancerNode.ApplyWeight.
  • Added Asset Labels to most assets.
  • Added IAnimationClipCollection which takes an ICollection instead of a List so it can use HashSets to efficiently avoid duplicates.
    • All Transitions now implement IAnimationClipCollection.
    • Added various Gather methods to AnimancerUtilities.
    • Moved the reflection based clip gathering system from AnimancerEditorUtilities into a dedicated AnimationGatherer class and improved its reliability.
    • It now finds the character's root object using the prefab root or by counting the number of Animators below each parent. An object with more Animators is assumed to be the parent of multiple characters, so the previous object is the root. Once it finds the root, it gathers animations from the child components of that object.
    • Added ICharacterRoot for components to manually specify which object is the root.
  • Added AnimancerStateDictionary.Destroy methods for collections and IAnimationClipSource.
  • The Find Animations context menu function for DirectionalAnimationSets now properly supports undo commands.
  • Added AnimancerUtilities.Wrap01 extension method as a more efficient implementation of Mathf.Repeat(value, 1).
  • Reorganised the Inspector context menus.
  • Removed AnimancerState.HasLength. All states must now return a valid Length (even if it is 0).
    • Added ManualMixerState.Length which is calculated as the weighted average of the lengths of each of its children.
  • Added ControllerState.StateInfo to return either the current or next state depending on whether a transition is active.
    • Length and IsLooping now use the StateInfo.
    • Removed ControllerState.Drawer.DisplayStateInfo, DisplayTime, DisplayLength, and SetTime since they are now unnecessary.
  • Added [<see cref="SerializeField"/>] tags to the start of comments for all properties that directly wrap serialized fields.
  • StateMachine.CanSetState now returns true if the parameter is null since the other methods support nulls.
  • The ReadMe now includes the Animancer Version in its name to better detect if the user did not delete a previous version before updating (since Unity's package importer will overwrite old files but not rename them).

Fixes

  • Fixed various issues in Unity 2019.3:
    • Fixed the preview icon to use a different texture since the old one seems to be missing.
    • Fixed AnimancerGUI.DoOptionalTimeField.
    • Fixed the event drawer foldout.
    • Fixed Inspector Error on the NamedAnimancerComponent.
    • Fixed import warnings from the Spider Bot model due to multiple objects having the same name.
    • Added a workaround so the base TransitionDrawer does not take proprity over its more specific children (only happens in a DLL).
  • Added DummyObjectDrawer as a fallback custom Inspector for any Object ... which does nothing (the class literally just inherits from UnityEditor.Editor and has no members). For some reason Unity executes PropertyDrawers differently in the default Inspector than it does in a custom Inspector (even an empty one) and that difference causes the TimeRuler to not display properly without a custom Inspector. Since it is set as a fallback, any other custom Inspector should automatically override it, but if not you can simply delete Animancer/Internal/Editor Utilities/Inspector/DummyObjectEditor.cs.
  • Fixed FadeMode.FromStart to work properly with the fadeDuration set to 0.
  • Fading now accounts for the speed of the parent nodes.
  • Fixed ControllerState.GatherDefaultStates to properly gather the state for layer 0.
  • Fixed transitions to use the correct label for the main property in Unity 2018.3+.
  • Fixed ManualMixerTransition.CreateState to properly call Initialize to create its states.
  • Removed the functionality to update animations in Edit Mode from Unity 2018.3+ because Unity now does it automatically.
  • Fixed the Edit Mode update loop to not throw exceptions when an object is destroyed.
  • Calling AnimancerState.SetParent with an already occupied port will now leave the state properly disconnected as it fails.
  • Fixed AnimancerPlayable.KeepChildrenConnected = true to work properly.
  • Fixed the AnimancerStateDrawer progress bars to be properly visible in the Dark Theme and changed the colors to be a bit stronger overall.
  • The AnimancerPlayable finalizer will no longer destroy the graph automatically while in Play Mode since that would mean a runtime warning anyway.
  • AnimancerState.Duration now returns PositiveInfinity from the getter if Speed is 0 and throws an ArgumentException is setting the value to 0.
  • AnimancerState.RemainingDuration now respects looping/not and custom end times.
  • Fixed the 2D mixer states to round children with weight < 0.01f to 0. Otherwise they often get very small weights and still trigger Animation Events.
  • PlayableGraphs created in Edit Mode are now destroyed properly if the target Animator is destroyed.
  • Added comments explaining that when OnAnimatorIK is called the layer index parameter will always be zero (a limitation of the Playables API).
  • Replaced all usage of EditorStyles.label with GUI.skin.label since they are slightly different in some Unity versions and the latter is the default used by GUI.Label.
  • Fixed the End Event/Clear context menu function to be disabled when the time is not set.
  • Ctrl + Click on a state in the Inspector now unpauses the graph as well as fading to that state.
  • Fixed Float3ControllerState to show all of its parameters in the Inspector rather than only the first two.

Examples

  • Added Weapons which uses the new instructions for downloading animations from Mixamo and configure their Import settings.
  • Improved the ReadMe:
    • It now lists all example scenes for easy navigation.
    • Improved the Inspector layout and added descriptions of each of the support links.
    • It now includes the Animancer Version in its name to better detect if the user did not delete a previous version before updating (since Unity's package importer will overwrite old files but not rename them).
  • Renamed Simple Playing to Quick Play.
  • Added Hybrid Basics to demonstrate the HybridAnimancerComponent in a simple situation without the complexity of a full state machine in Hybrid Mini Game.
  • Improved Sequence Coroutine:
    • It now uses the new custom end time system rather than needing a ClipTransition subclass with its own PlayDuration field.
    • Added assertions for reliability.
  • Improved Speed and Time and Directional Blending:
    • They now use a shared SpiderBot base class and demonstrate polymorphism.
    • SpiderBotAdvanced now follows the mouse cursor so it can truly move in any direction rather than being limited to 8 directions with WASD.
    • Cleaned up the animation names to match the same convention as others.
  • Improved RootMotion:
    • It now overrides Transition.Apply to set the root motion flag so the caller doesn't need to do it.
    • It now has some extra fields to specify another object to apply the root motion to.
  • Linear Blending now uses Transition Assets.
  • Directional Basics now uses a serialized field so its initial facing direction can be set in Edit Mode and it now has a dedicated Play method which takes a DirectionalAnimationSet instead of callingGetClip in each location it wants to play something.
  • Renamed the "Animation Events" group to Events (since they now demonstrate Animancer Events as well).
  • Renamed "Simple and End Events" to Golf Events and updated it to demonstrate regularAnimation Events, a SimpleEventReceiver, Animancer Events defined in the Inspector, and Animancer Events with their times se in the Inspector and callbacks set in code.
  • Renamed "Other Events" to Footstep Events and reordered it to come before "Golf Events".
    • It now includes Animancer Events and much more detail about how to set everything up.
  • Brain Transplants now enables and disables the brains in code when swapping them instead of using the UnityEvents on the UI Buttons. #10
  • Improved Platformer:
    • Added an introduction sequence using Timeline.
    • Jumping now uses a specific target height rather than an arbitrary amount of force.
    • It now allows the player to jump higher by holding the button longer.
    • Reviving the character now plays the death animation backwards.
  • Improved the Inverse Kinematics examples:
    • Changed StartingPositions to TransformResetter and it now resets rotations as well.
    • Improved RaycastFootIK to account for the foot rotation when calculating the raycast diration.
  • Hybrid Mini Game now has the character walk into and out of the mini game rather than teleporting.
  • Improved 3D Game Kit:
    • It is now based on the 3D Game Kit Lite since the full version is a massive pain to download and import. #11
    • It now shows which system (Animancer or Mecanim) is active and lets you swap between them with keyboard controls instead of UI Buttons.
    • It now uses custom end times as part of each transition rather than End Animation Events or separate end time fields.
    • The root object is now separate from the model with RootMotionRedirect passing on the root motion.
    • AirborneState and LandingState now use Mixers instead of Blend Trees since they are more convenient to use and can give the same result now that time synchronization has been implemented.
    • Added FlinchState and DieState.
    • Attacks can how kill enemies and destroy objects and do not use a custom transition class.
    • Removed the copy of RandomAudioPlayer and used UnityEvents to access the existing script.
    • Removed the copy of AttackTrail and used UnityEvents to access the existing TimeEffect script.
  • Added [DefaultExecutionOrder] attributes to all Character examples as well as comments in Awake to reinforce its importance.

Internal

  • Added 150+ unit tests using the Unity Test Framework. The tests are not planned for release so they will not directly matter to users, but they will help reduce the possibility of bugs making it to release.
  • Changed AnimancerNode.Stop from abstract to virtual so it can set Weight = 0 by default since both AnimancerLayer and AnimancerState did so.
  • Moved the functionality to constantly repaint in Edit Mode from the manual update loop to AnimancerPlayableEditor.RequiresConstantRepaint.
  • Split AnimancerPlayableEditor into BaseAnimancerComponentEditor and AnimancerPlayableDrawer to the preview window can draw its AnimancerPlayable without actually having an AnimancerComponent.
  • Moved FastComparer out of AnimancerPlayable.
  • Changed AnimancerLayer.DestroyStates and ManualMixerState.DestroyChildren to iterate in reverse order.
  • Moved AnimancerEditorUtilities.GUIStyles out to AnimancerGUI and moved all GUI utilities there.
    • Renamed GetLayoutRect to LayoutSingleLineRect.
    • Added padding parameter to StealFromLeft and StealFromRight.
  • Changed parameter references in comments to use the `grave accent` instead of 'single quotes'.
  • Added ConversionCache to replace various other caching systems throughout Animancer.
  • Added TemporarySettings for storing information between assembly reloads without needing to save it when Unity closes.
    • Currently it is used to store details about which Animancer Events are selected in the Inspector.
    • Added ITransitionDetailed : ITransition to expose additional details for previewing.
  • Added Key and Key.KeyedList:
    • Changed AnimancerNode to inherit from Key and replaced the dirty node update list with a keyed list which greatly cleans up that part of the system.
    • Changed IEarlyUpdate into IUpdatable which implements IKeyHolder and replaced its list with a keyed list as well.
    • Removed the needsMoreUpdates parameter from IUpdatable.Update since they can be immediately removed at any time by AnimancerPlayable.CancelUpdate.
  • Added a simple ObjectPool system to allow easy reuse of objects. If you want a more powerful general purpose system, check out Weaver.
  • Refactored the AppendDescription system in the core classes to be cleaner and produce better descriptions.
  • Added Serialization class which contains various utilities relating to serialization:
    • Serialization.PropertyAccessor allows access to the underlying object of a SerializedProperty.
    • Serialization.ObjectReference acts as a stronger serializable reference to a UnityEngine.Object. A simple Object field can lose its value under certain circumstances even if the referenced object still exists, for example when entering Play Mode.
    • Serialization.PropertyReference is a serializable reference to a SerializedProperty.
  • Moved the custom GUI for the Start Time and Speed fields to the base TransitionDrawer.
  • All calls to EditorGUI.Foldout now set EditorGUIUtility.hierarchyMode = true to ensure that the arrow gets the correct indentation.