KybernetikGames / animancer

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

v7 Referencing UnShared assets in ScriptableObjects #359

Closed hariedo closed 3 weeks ago

hariedo commented 4 weeks ago

Have been using UnShared transition assets in prefabbed characters for a while but was looking to make a higher-level grouping of transitions, etc., in a ScriptableObject.

Before: a Prefab has a List<P> and P has a member which refers to an UnShared asset. The Prefab is serialized into the scene multiple times, so each instance ends up with its own mixer.State.Parameter.

After: a Prefab has a reference to an SO, the SO has a List<P> and P has a member which refers to an UnShared asset. Since the Prefab is not independently serializing the SO into each instance, this chain ends up sharing a single UnShared instance. One instance works fine, two instances clobber the now-shared mixer.State.Parameter.

If I could just .Clone() the MixerTransition2D.UnShared when an instance starts it seems like it would work. It looks like MixerTransition2D is ICopyable but the MixerState is not. Just calling CreateState() for each instance that refers to the asset does not make two instances independent. Using NewtonSoft to deep serialize the UnShared doesn't even seem to make them independent, and of course UnityEditor.JsonUtility is off-limits to the runtime.

Ideas?

KybernetikGames commented 4 weeks ago

If the UnShared field is in a location where it's being shared then it won't work so you might as well just directly reference the target Transition Asset there. This is a big part of why they were removed and the whole event system reworked in Animancer v8.0. Also, the new Mixer Parameter Binding system might avoid your need to directly access the state entirely.

I'm not at home at the moment so I don't have the old code in front of me, but from what I can remember if you want to clone an UnShared you can just create a new MixerTransition2D.UnShared() and assign the same Asset to it.

hariedo commented 3 weeks ago

This seems to work.


if (mixer != null)
    clone.mixer = new MixerTransition2DAsset.UnShared();
if (mixer.HasAsset)
    clone.mixer.Asset = mixer.Asset;```