You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

328 lines
12 KiB

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<int, int> m_AnimsDict;
private List<AnimacerData> 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<int, int>.Pop();
m_AnimList = ListPool<AnimacerData>.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<AnimacerData>.Free(ref animParam);
}
ListPool<AnimacerData>.Push(ref m_AnimList);
DictionaryPool<int, int>.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<AnimacerData>.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<AnimacerData>.Free(ref param);
m_AnimList.RemoveAt(anim);
m_AnimsDict.Remove((int)skinParam.bpType);
}
var malloc = SptPool<AnimacerData>.Malloc();
var subGo = subAssetData.reuseGoData.go;
// 缓存一下吧,go的组件,和怪物角色类型绑定的
if (subGo.TryGetComponent<NamedAnimancerComponent>(out var animComponent) == false)
{
var animator = subGo.GetComponentInChildren<Animator>();
if (!animator)
{
XLog.LogWarning("No Animator Component");
SptPool<AnimacerData>.Free(ref malloc);
return;
}
animComponent = subGo.AddComponent<NamedAnimancerComponent>();
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;
}
}
}