using System; using System.Collections.Generic; using Animancer; using AOT; using GAS.Runtime; using UnityEngine; using UnityEngine.Playables; using xFrame; using YooAsset; namespace CoreGame.Render { [Combat] public class AnimationProxy : ProxyBase { public class AnimacerData : ISptPool { public NamedAnimancerComponent animComponent; public AssetHandle actionLayerMaskHandle; public bool layerInited; public FName animPrefix; public FName animPathParam; public void Reset() { // actionLayerMaskHandle?.Release(); actionLayerMaskHandle = null; animComponent = null; animPrefix = default; animPathParam = default; layerInited = false; } } public struct PlayParam { public FName stateName; public float speed; public bool needClear; public bool isForce; // 权限最高 public bool isFromStart; public static bool operator ==(in PlayParam left, in PlayParam right) { return left.stateName.comparisonIndex == right.stateName.comparisonIndex && Mathf.Approximately(left.speed, right.speed) && left.isForce == right.isForce; } public static bool operator !=(in PlayParam left, in PlayParam right) { return !(left == right); } public override string ToString() { return stateName.GetDisplayString() + " speed: " + speed + " isForce: " + isForce + " isFromStart: " + isFromStart; } } private bool m_HasActionLayer; private Dictionary m_AnimsDict; private List m_AnimList; private readonly PlayParam[] m_WantLayerState = new PlayParam[2]; internal readonly PlayParam[] currLayerState = new PlayParam[2]; protected override void Initialize(GameObject go, CombatEntity ent) { m_HasActionLayer = false; m_AnimsDict = DictionaryPool.Pop(); m_AnimList = ListPool.Pop(); Array.Clear(m_WantLayerState, 0, m_WantLayerState.Length); Array.Clear(currLayerState, 0, currLayerState.Length); } protected override void OnReset() { for (int i = 0; i < m_AnimList.Count; i++) { var animParam = m_AnimList[i]; // Object.Destroy(animParam.animComponent); SptPool.Free(ref animParam); } ListPool.Push(ref m_AnimList); DictionaryPool.Push(ref m_AnimsDict); } public void PushMainAnimancer(in SubAssetData subAssetData, in SkinParam skinParam) { PushPartAnimancer(subAssetData, skinParam); } public bool PopPartAnimancer(in SubAssetData subAssetData, in SkinParam skinParam) { if (m_AnimsDict.TryGetValue((int)skinParam.bpType, out int anim)) { var param = m_AnimList[anim]; SptPool.Free(ref param); m_AnimList.RemoveAt(anim); m_AnimsDict.Remove((int)skinParam.bpType); return true; } return false; } public void PushPartAnimancer(in SubAssetData subAssetData, in SkinParam skinParam) { if (m_AnimsDict.TryGetValue((int)skinParam.bpType, out int anim)) { var param = m_AnimList[anim]; SptPool.Free(ref param); m_AnimList.RemoveAt(anim); m_AnimsDict.Remove((int)skinParam.bpType); } var malloc = SptPool.Malloc(); var subGo = subAssetData.reuseGoData.go; // 缓存一下吧,go的组件,和怪物角色类型绑定的 if (subGo.TryGetComponent(out var animComponent) == false) { var animator = subGo.GetComponentInChildren(); if (!animator) { XLog.LogWarning("No Animator Component"); SptPool.Free(ref malloc); return; } animComponent = subGo.AddComponent(); animator.runtimeAnimatorController = null; animComponent.Animator = animator; animComponent.Playable.UpdateMode = DirectorUpdateMode.Manual; // 目前只有主角的,主动画有动作层 if (skinParam.bpType == BindPointType.Main) { malloc.actionLayerMaskHandle = AnimationSrv.GetMaskHandle(skinParam.animPrefix, skinParam.path); } } malloc.animComponent = animComponent; malloc.animPrefix = skinParam.animPrefix; malloc.animPathParam = skinParam.path; m_AnimList.Add(malloc); m_AnimsDict.Add((int)skinParam.bpType, m_AnimList.Count - 1); } // isForce 权限最高,低优先级可中断高优先级动作 public void Play(in FName stateName, float speed = 1f, bool isForce = false, bool isFromStart = false) { var fName = stateName; var tbAnim = AnimationSrv.StatePriorityDescMap[fName]; if (tbAnim == null) return; if (isForce == false) { // 也要有互斥 var canTransformState = AnimationSrv.CanTransformState(m_WantLayerState[tbAnim.layer].stateName, fName, 0, isFromStart); if (!canTransformState) return; } m_WantLayerState[tbAnim.layer] = new PlayParam { stateName = fName, speed = speed, isForce = m_WantLayerState[tbAnim.layer].isForce || isForce , isFromStart = isFromStart}; } public void Tick(float deltaTime) { for (int i = 0; i < m_WantLayerState.Length; i++) m_WantLayerState[i].needClear = true; // 部件很少了,就一把枪 for (int i = 0; i < m_AnimList.Count; i++) { var mAnimacerData = m_AnimList[i]; InitAvatarMask(mAnimacerData); for (int j = 0; j < m_WantLayerState.Length; j++) { var needChangeState = Do(mAnimacerData, j); m_WantLayerState[j].needClear &= needChangeState; } } for (int i = 0; i < m_WantLayerState.Length; i++) { if (m_WantLayerState[i].needClear) m_WantLayerState[i] = new PlayParam(); } // 自旋 for (var index = 0; index < m_AnimList.Count; index++) { var animComponent = m_AnimList[index].animComponent; animComponent.Evaluate(deltaTime); if (ent.isDead) // 死亡不stop continue; var animComponentLayers = animComponent.Layers; // 中断已播放到末尾,非loop的动画 for (int i = 0; i < animComponentLayers.Count; i++) { var layer = animComponentLayers.GetLayer(i); var layerCurrentState = layer.CurrentState; if (layerCurrentState == null) continue; if (layerCurrentState.NormalizedTime >= 1 && layerCurrentState.IsLooping == false) { layer.Stop(); currLayerState[i] = new PlayParam(); } } } } private void InitAvatarMask(AnimacerData animacerData) { if (animacerData.layerInited == false) { if (animacerData.actionLayerMaskHandle != null && animacerData.actionLayerMaskHandle.IsDone) { if (animacerData.actionLayerMaskHandle.AssetObject is AvatarMask mask) { animacerData.animComponent.Layers[1].SetMask(mask); m_HasActionLayer = true; } animacerData.layerInited = true; } } } private bool Do(AnimacerData animacerData, int idx) { ref var wantParam = ref m_WantLayerState[idx]; if (wantParam.stateName.IsValid() == false) return false; if (!m_HasActionLayer) idx = 0; var assetHandle = AnimationSrv.GetClipAndLoadHandle(animacerData.animPrefix, wantParam.stateName, animacerData.animPathParam); // 没动画的话,就不处理了 if (assetHandle == null || !assetHandle.IsDone) { return false; } if (assetHandle.AssetObject is not AnimationClip clip) { return true; } var tbAnimationStatePriority = AnimationSrv.StatePriorityDescMap[wantParam.stateName]; // 获取层级 var layer = 0; if (tbAnimationStatePriority.layer <= animacerData.animComponent.Layers.Count - 1) { layer = tbAnimationStatePriority.layer; } //当前动画层 var currLayer = animacerData.animComponent.Layers[layer]; // 相同状态,变速 var currLayerCurrentState = currLayer.CurrentState; do { if (currLayerCurrentState == null) break; // 自己在播 var isCurrPlaying = currLayerCurrentState.Clip == clip && (currLayerCurrentState.IsLooping || currLayerCurrentState.NormalizedTime < 0.99f); if (isCurrPlaying) { if (wantParam.isFromStart) { // Debug.LogError(layer + animacerData.animComponent.gameObject.name + " " + wantParam.stateName.GetDisplayString()); currLayerCurrentState.NormalizedTime = 0; // currLayer.Play(clip, 0, FadeMode.FromStart); currLayerCurrentState.Speed = wantParam.speed; // wantParam.isFromStart = false; return true; } if (Mathf.Approximately(wantParam.speed, currLayerCurrentState.Speed)) { return true; } for (var index = 0; index < m_AnimList.Count; index++) { var anim = m_AnimList[index]; anim.animComponent.Layers[layer].CurrentState.Speed = wantParam.speed; } return true; } // if (currLayerCurrentState.NormalizedTime < 0.99f) { var tags = ent.TagCountContainer; if (tags != null) { // 要有互斥规则 if (wantParam.stateName.GetDisplayString() != "die" && tags.HasTag(GTagLib.State_Death)) return false; } var normalizedTime = currLayerCurrentState.NormalizedTime; if (currLayerCurrentState.IsLooping) normalizedTime = 0; if (wantParam.isForce) break; // 判断是否可以切换动画 if (!AnimationSrv.CanTransformState(currLayerState[idx].stateName, wantParam.stateName, normalizedTime, wantParam.isFromStart)) return false; } } while (false); // for (var index = 0; index < m_AnimList.Count; index++) { currLayer.Play(clip); // wantParam.isFromStart = false; currLayerState[idx] = wantParam; currLayer.CurrentState.Speed = wantParam.speed; } return true; } } }