// Animancer // https://kybernetik.com.au/animancer // Copyright 2018-2023 Kybernetik // using System.Collections.Generic; using UnityEngine; namespace Animancer { /// A system for synchronizing the of certain animations. /// /// /// Initialize a by adding any objects you want to synchronize. /// Call any of the methods before playing a new animation. /// Call any of the methods after playing that animation. /// /// Example: Character Controller -> Synchronization /// /// https://kybernetik.com.au/animancer/api/Animancer/TimeSynchronizationGroup /// public class TimeSynchronizationGroup : HashSet { /************************************************************************************************************************/ private AnimancerComponent _Animancer; /// The this group is synchronizing. /// /// This reference is not required if you always use the store and sync methods that take an /// . /// public AnimancerComponent Animancer { get => _Animancer; set { _Animancer = value; NormalizedTime = null; } } /************************************************************************************************************************/ /// The stored or null if no value was stored. public float? NormalizedTime { get; set; } /************************************************************************************************************************/ /// Creates a new and sets its . public TimeSynchronizationGroup(AnimancerComponent animancer) => Animancer = animancer; /************************************************************************************************************************/ /// /// Stores the of the 's current state if /// the `key` is in this group. /// public bool StoreTime(object key) => StoreTime(key, Animancer.States.Current); /// /// Stores the of the `state` if the `key` is in this group. /// public bool StoreTime(object key, AnimancerState state) { if (state != null && Contains(key)) { NormalizedTime = state.NormalizedTime; return true; } else { NormalizedTime = null; return false; } } /************************************************************************************************************************/ /// /// Applies the to the 's current state if the `key` is in /// this group. /// public bool SyncTime(object key) => SyncTime(key, Time.deltaTime); /// /// Applies the to the 's current state if the `key` is in /// this group. /// public bool SyncTime(object key, float deltaTime) => SyncTime(key, Animancer.States.Current, deltaTime); /// Applies the to the `state` if the `key` is in this group. public bool SyncTime(object key, AnimancerState state) => SyncTime(key, state, Time.deltaTime); /// Applies the to the `state` if the `key` is in this group. public bool SyncTime(object key, AnimancerState state, float deltaTime) { if (NormalizedTime == null || state == null || !Contains(key)) return false; // Setting the Time forces it to stay at that value after the next animation update. // But we actually want it to keep playing, so we need to add deltaTime manually. state.Time = NormalizedTime.Value * state.Length + deltaTime * state.EffectiveSpeed; return true; } /************************************************************************************************************************/ } }