KybernetikGames / animancer

Documentation for the Animancer Unity Plugin.
66 stars 8 forks source link

How Best To Organize Animations #277

Closed AlexAdach closed 1 year ago

AlexAdach commented 1 year ago

Hi,

Love Animancer. I'm still new to Unity but it was pretty clear for me from the start that mechanim was going to be a PITA to scale. Glad I stumbled on your plugin.

I'm trying to figure out how best to organize my animations. My most recent experiment was to create a scriptable object that was to be a characters full animation set. In this asset, I defined a class called AnimationSetDetails that had a ITransitionDetailed as well as some other properties. There's an intensity property for example, so when my FSM tells my animancer component to play a locomotion animation with an intensity of 2, it would look through the list of AnimationSetDetails, find animations that fit the "animationtype" (locomotion, walkstart, walkstop, jump, etc). and from that list of animations, find the set that had an intensity of 2, and if there wasn't one, to find the next best available.

This was working OK, but I was running into problems while editing the list of AnimationSetDetails inside my scriptable object. It seems that whenever I tried to modify the list, other elements in that list would get affected. I'm assuming this is because I wasn't properly instantiating a new AnimationSetDetail when I modified the list, and elements in the list were referencing each other. I spent several hours scouring the internet, it's tough to find details on this but it seems like I need to create a custom editor script. I then found a video that suggested creating a scriptable object that could create a list of nested scriptable objects inside of it.

You touch on transitionassets and scriptable objects in the docs, but I'm just wondering if you had any guidance on how to create reusable character animation set assets? Specifically If I want to associate custom properties with each ITransition. Here's my scriptable object I was talking about I'd appreciate any feedback.


using Animancer;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Runtime.CompilerServices;
using UnityEngine;

[CreateAssetMenu(fileName = "CharacterAnimationSet", menuName = "AnimationSets/CharacterAnimationSet", order = 1)]
public class CharacterAnimationSet : ScriptableObject
{
    [SerializeReference] public ITransitionDetailed TPose;

    [SerializeField] private List<AnimationSetDetails> _animations;
    public ReadOnlyCollection<AnimationSetDetails> Animations { get { return _animations.AsReadOnly(); } }

}

[Serializable]
public class AnimationSetDetails
{
    [SerializeField] private string _friendlyName;
    [SerializeField] private int _intensity;
    [SerializeField] private AnimationType _type;
    [SerializeReference] private ITransitionDetailed _animationSet;

    public string FriendlyName { get => _friendlyName; }
    public int Intensity { get => _intensity; }
    public AnimationType Type { get => _type; }
    public ITransitionDetailed AnimationSet { get => _animationSet; }

    public AnimationSetDetails()
    {
        _friendlyName = "";

    }

}
KybernetikGames commented 1 year ago

When you increase the size of an array in the Inspector, Unity clones the last item into all the new slots. For regular serialized fields that means they're all separate copies, but [SerializeReference] fields can actually have multiple fields referencing the same object, so you're getting multiple array items all pointing to the same underlying data.

You can avoid that by using the dropdown menu to pick the type of each new array item because that creates a new object so they won't be referencing the same thing anymore.

In my To Do list for the next major version I want to see if I can figure out a way to detect when multiple fields are referencing the same thing so I can indicate that in the Inspector somehow (and to do it intentionally since it could potentially be useful).