2023-06-08 14:09:50 +08:00
|
|
|
using System;
|
|
|
|
using System.Collections;
|
|
|
|
using System.Collections.Generic;
|
2023-11-30 00:23:23 +08:00
|
|
|
using System.Linq;
|
2023-11-15 23:54:54 +08:00
|
|
|
using System.Text;
|
2023-06-08 14:09:50 +08:00
|
|
|
using UnityEngine;
|
|
|
|
using System.Threading;
|
|
|
|
using System.Threading.Tasks;
|
|
|
|
using Unity.Mathematics;
|
2023-11-30 00:23:23 +08:00
|
|
|
|
2023-06-08 14:09:50 +08:00
|
|
|
namespace BITKit.Animations
|
|
|
|
{
|
2023-11-30 00:23:23 +08:00
|
|
|
public static class UnityAnimatorExtensions
|
|
|
|
{
|
|
|
|
public static AnimatorOverrideController CopyAndFillMissingContent(
|
|
|
|
this AnimatorOverrideController originalOverrideController, AnimatorOverrideController runtimeController)
|
|
|
|
{
|
|
|
|
var newOverrideController = new AnimatorOverrideController(runtimeController)
|
|
|
|
{
|
|
|
|
runtimeAnimatorController = originalOverrideController.runtimeAnimatorController,
|
|
|
|
};
|
|
|
|
|
|
|
|
Dictionary<AnimationClip, AnimationClip> clips = new();
|
|
|
|
List<KeyValuePair<AnimationClip, AnimationClip>> sourceClips = new();
|
|
|
|
List<KeyValuePair<AnimationClip, AnimationClip>> destinationClips = new();
|
|
|
|
|
|
|
|
originalOverrideController.GetOverrides(sourceClips);
|
|
|
|
runtimeController.GetOverrides(destinationClips);
|
|
|
|
|
|
|
|
List<KeyValuePair<AnimationClip, AnimationClip>> newClips = new();
|
|
|
|
foreach (var VARIABLE in sourceClips)
|
|
|
|
{
|
|
|
|
if (VARIABLE.Key is not null && VARIABLE.Value is not null)
|
|
|
|
clips.TryAdd(VARIABLE.Key, VARIABLE.Value);
|
|
|
|
}
|
|
|
|
foreach (var VARIABLE in destinationClips)
|
|
|
|
{
|
|
|
|
if (VARIABLE.Key is not null)
|
|
|
|
clips.TryAdd(VARIABLE.Key, VARIABLE.Value);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// foreach (var VARIABLE in sourceClips)
|
|
|
|
// {
|
|
|
|
// if (clips.TryGetValue(VARIABLE.Key, out var clip))
|
|
|
|
// {
|
|
|
|
// newClips.Add(new KeyValuePair<AnimationClip, AnimationClip>(clip, VARIABLE.Value));
|
|
|
|
// }
|
|
|
|
// }
|
|
|
|
|
|
|
|
newOverrideController.name = $"{originalOverrideController.name} Combine";
|
|
|
|
newOverrideController.ApplyOverrides(
|
|
|
|
clips.Select(x=>new KeyValuePair<AnimationClip,AnimationClip>(x.Key,x.Value)).ToList()
|
|
|
|
);
|
|
|
|
return newOverrideController;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-06-08 14:09:50 +08:00
|
|
|
public class UnityAnimator : MonoBehaviour, IAnimator
|
|
|
|
{
|
2023-11-30 00:23:23 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
2023-10-24 23:37:59 +08:00
|
|
|
[Serializable]
|
2023-06-08 14:09:50 +08:00
|
|
|
public class AnimatorLayerInfo
|
|
|
|
{
|
2023-11-15 23:54:54 +08:00
|
|
|
public string LayerName;
|
2023-06-08 14:09:50 +08:00
|
|
|
public string stateName;
|
|
|
|
public string fullStateName;
|
2023-10-24 23:37:59 +08:00
|
|
|
internal string entryName;
|
2023-06-08 14:09:50 +08:00
|
|
|
public AnimatorStateInfo currentState = new();
|
|
|
|
public event Action<string> onStateEnter;
|
|
|
|
public event Action<string> onStateExit;
|
|
|
|
public void OnStateEnter(string name)
|
|
|
|
{
|
|
|
|
onStateEnter?.Invoke(name);
|
|
|
|
}
|
|
|
|
public void OnStateExit(string name)
|
|
|
|
{
|
|
|
|
onStateExit?.Invoke(name);
|
|
|
|
}
|
|
|
|
}
|
2023-10-24 23:37:59 +08:00
|
|
|
|
|
|
|
[Header(Constant.Header.Settings)]
|
|
|
|
[SerializeField] private bool debug;
|
|
|
|
|
2023-06-08 14:09:50 +08:00
|
|
|
[Header(Constant.Header.Components)]
|
|
|
|
public Animator animator;
|
|
|
|
public AnimatorLayerInfo this[int index]
|
|
|
|
{
|
|
|
|
get
|
|
|
|
{
|
|
|
|
if (layerInfos.Count <= index)
|
|
|
|
{
|
|
|
|
for (int i = layerInfos.Count - 1; i < index; i++)
|
|
|
|
{
|
2023-11-15 23:54:54 +08:00
|
|
|
var newLayer = new AnimatorLayerInfo
|
|
|
|
{
|
|
|
|
LayerName = animator.GetLayerName(i+1)
|
|
|
|
};
|
|
|
|
layerInfos.Add(newLayer);
|
2023-06-08 14:09:50 +08:00
|
|
|
}
|
|
|
|
}
|
2023-08-12 01:43:24 +08:00
|
|
|
|
|
|
|
if (index > layerInfos.Count - 1)
|
|
|
|
{
|
|
|
|
throw new Exception("Index out of range");
|
|
|
|
}
|
2023-06-08 14:09:50 +08:00
|
|
|
return layerInfos[index];
|
|
|
|
}
|
|
|
|
}
|
2023-10-24 23:37:59 +08:00
|
|
|
[SerializeField] private List<AnimatorLayerInfo> layerInfos = new();
|
2023-08-12 01:43:24 +08:00
|
|
|
[Header(Constant.Header.InternalVariables)]
|
|
|
|
private readonly Dictionary<string,UnityAnimatorStateInfo> _registryStates=new ();
|
2023-10-24 23:37:59 +08:00
|
|
|
|
|
|
|
private void OnEnable()
|
|
|
|
{
|
|
|
|
animator.enabled = true;
|
|
|
|
}
|
|
|
|
private void OnDisable()
|
|
|
|
{
|
|
|
|
animator.enabled = false;
|
|
|
|
foreach (var x in layerInfos)
|
|
|
|
{
|
|
|
|
x.entryName = null;
|
|
|
|
}
|
|
|
|
}
|
2023-11-15 23:54:54 +08:00
|
|
|
public void CrossFade(string animationName, float duration, int index = 0, float normalizedTimeOffset = 0)
|
2023-06-08 14:09:50 +08:00
|
|
|
{
|
2023-11-15 23:54:54 +08:00
|
|
|
animator.CrossFade(GetVariableName(animationName), duration, index, normalizedTimeOffset);
|
2023-06-08 14:09:50 +08:00
|
|
|
}
|
2023-08-12 01:43:24 +08:00
|
|
|
|
2023-11-15 23:54:54 +08:00
|
|
|
public void Play(string animationName, int index = -1, float normalizedTimeOffset = 0)
|
2023-06-08 14:09:50 +08:00
|
|
|
{
|
2023-11-15 23:54:54 +08:00
|
|
|
if (debug)
|
2023-06-08 14:09:50 +08:00
|
|
|
{
|
2023-11-15 23:54:54 +08:00
|
|
|
BIT4Log.Log<UnityAnimator>( $"{gameObject.name} Play:" + animationName);
|
2023-06-08 14:09:50 +08:00
|
|
|
}
|
2023-11-15 23:54:54 +08:00
|
|
|
animator.Play(GetVariableName(animationName), index, normalizedTimeOffset);
|
2023-08-12 01:43:24 +08:00
|
|
|
}
|
|
|
|
|
2023-06-08 14:09:50 +08:00
|
|
|
public void OnStateEnter(int index, string name)
|
|
|
|
{
|
2023-10-24 23:37:59 +08:00
|
|
|
if (debug)
|
|
|
|
{
|
|
|
|
BIT4Log.Log<UnityAnimator>($"OnEntry:{name}");
|
|
|
|
}
|
2023-06-08 14:09:50 +08:00
|
|
|
this[index].fullStateName = name;
|
|
|
|
foreach (var item in name.Split("."))
|
|
|
|
{
|
|
|
|
name = item;
|
|
|
|
break;
|
|
|
|
}
|
2023-10-24 23:37:59 +08:00
|
|
|
this[index].stateName = this[index].entryName = name;
|
2023-06-08 14:09:50 +08:00
|
|
|
this[index].OnStateEnter(name);
|
|
|
|
}
|
|
|
|
public void OnStateExit(int index, string name)
|
|
|
|
{
|
2023-10-24 23:37:59 +08:00
|
|
|
if (string.IsNullOrEmpty(this[index].entryName))
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (debug)
|
|
|
|
{
|
|
|
|
BIT4Log.Log<UnityAnimator>($"OnExit:{name}");
|
|
|
|
}
|
2023-06-08 14:09:50 +08:00
|
|
|
this[index].OnStateExit(name);
|
|
|
|
}
|
|
|
|
public float3 GetRootVelocity()
|
|
|
|
{
|
|
|
|
return animator.velocity;
|
|
|
|
}
|
2023-08-12 01:43:24 +08:00
|
|
|
|
|
|
|
private void Start()
|
|
|
|
{
|
|
|
|
foreach (var x in animator.GetBehaviours<UnityAnimatorStateInfo>())
|
|
|
|
{
|
2023-11-15 23:54:54 +08:00
|
|
|
try
|
|
|
|
{
|
|
|
|
_registryStates.TryAdd(x.StateName, x);
|
|
|
|
foreach (var v in x.VariableNames)
|
|
|
|
{
|
|
|
|
_registryStates.TryAdd(v, x);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
catch (Exception e)
|
|
|
|
{
|
|
|
|
BIT4Log.Warning<UnityAnimator>(gameObject.name);
|
|
|
|
throw;
|
|
|
|
}
|
|
|
|
|
2023-08-12 01:43:24 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private void Update()
|
2023-06-08 14:09:50 +08:00
|
|
|
{
|
2023-08-12 01:43:24 +08:00
|
|
|
for (var i = 0; i < animator.layerCount; i++)
|
2023-06-08 14:09:50 +08:00
|
|
|
{
|
2023-08-12 01:43:24 +08:00
|
|
|
this[i].currentState = animator.GetCurrentAnimatorStateInfo(i);
|
2023-06-08 14:09:50 +08:00
|
|
|
}
|
|
|
|
}
|
2023-11-15 23:54:54 +08:00
|
|
|
|
|
|
|
[ContextMenu(nameof(Diagnosis))]
|
|
|
|
private void Diagnosis()
|
|
|
|
{
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
private string GetVariableName(string animationName)
|
|
|
|
{
|
|
|
|
animationName = animationName.Replace(".", "_");
|
|
|
|
|
|
|
|
if (!_registryStates.TryGetValue(animationName, out var stateInfo)) return animationName;
|
|
|
|
|
|
|
|
animationName = stateInfo.StateName;
|
|
|
|
if (stateInfo.VariableAnimationNames.Length > 0)
|
|
|
|
{
|
|
|
|
animationName = stateInfo.VariableAnimationNames.Random();
|
|
|
|
}
|
|
|
|
|
|
|
|
return animationName;
|
|
|
|
}
|
2023-06-08 14:09:50 +08:00
|
|
|
}
|
|
|
|
}
|