281 lines
9.4 KiB
C#
281 lines
9.4 KiB
C#
using System;
|
||
using Cysharp.Threading.Tasks;
|
||
using System.Collections.Generic;
|
||
using PhxhSDK;
|
||
using UnityEngine;
|
||
using Constants = Framework.Constants;
|
||
using Object = UnityEngine.Object;
|
||
|
||
namespace Gameplay.Character
|
||
{
|
||
public class CharacterAnim
|
||
{
|
||
|
||
public readonly Character owner;
|
||
|
||
public string targetDownAnim;
|
||
|
||
public string targetFullAnim;
|
||
|
||
public bool noFade = false;
|
||
|
||
public string currentDownAnim { get; private set; }
|
||
public string currentFullAnim { get; private set; }
|
||
|
||
public readonly Animator rawAnim;
|
||
|
||
private Dictionary<int, LTAnimLayerInfo> _layerDict;
|
||
|
||
private float _splitScaleNormalShoot = 1;
|
||
public float splitScaleNormalShoot
|
||
{
|
||
get
|
||
{
|
||
return _splitScaleNormalShoot;
|
||
}
|
||
set
|
||
{
|
||
if (Math.Abs(_splitScaleNormalShoot - value) < 0.01f) return;
|
||
_splitScaleNormalShoot = value;
|
||
rawAnim.SetFloat(EAnimParamConst.AttackScaleNormal, _splitScaleNormalShoot);
|
||
if (owner.weapon != null && owner.weapon.weaponAnim.rawAnim != null)
|
||
{
|
||
owner.weapon.weaponAnim.rawAnim.SetFloat(EAnimParamConst.AttackScaleNormal, _splitScaleNormalShoot);
|
||
}
|
||
}
|
||
}
|
||
|
||
private float _splitScaleNormalReload = 1;
|
||
public float splitScaleNormalReload
|
||
{
|
||
get
|
||
{
|
||
return _splitScaleNormalReload;
|
||
}
|
||
set
|
||
{
|
||
if (Math.Abs(_splitScaleNormalReload - value) < 0.01f) return;
|
||
_splitScaleNormalReload = value;
|
||
rawAnim.SetFloat(EAnimParamConst.ReloadScaleNormal, _splitScaleNormalReload);
|
||
if (owner.weapon != null && owner.weapon.weaponAnim.rawAnim != null)
|
||
{
|
||
owner.weapon.weaponAnim.rawAnim.SetFloat(EAnimParamConst.ReloadScaleNormal, _splitScaleNormalReload);
|
||
}
|
||
}
|
||
}
|
||
|
||
private float _splitScaleNormalMove = 1;
|
||
public float splitScaleNormalMove
|
||
{
|
||
get
|
||
{
|
||
return _splitScaleNormalMove;
|
||
}
|
||
set
|
||
{
|
||
if (Math.Abs(_splitScaleNormalMove - value) < 0.01f) return;
|
||
_splitScaleNormalMove = value;
|
||
rawAnim.SetFloat(EAnimParamConst.MoveScaleNormal, _splitScaleNormalMove);
|
||
}
|
||
}
|
||
private float _splitScaleLowMove = 1;
|
||
public float splitScaleLowMove
|
||
{
|
||
get
|
||
{
|
||
return _splitScaleLowMove;
|
||
}
|
||
set
|
||
{
|
||
if (Math.Abs(_splitScaleLowMove - value) < 0.01f) return;
|
||
_splitScaleLowMove = value;
|
||
rawAnim.SetFloat(EAnimParamConst.MoveScaleLow, _splitScaleLowMove);
|
||
}
|
||
}
|
||
|
||
private float _splitScaleRaiseWeapon = 1;
|
||
public float splitScaleRaiseWeapon
|
||
{
|
||
get
|
||
{
|
||
return _splitScaleRaiseWeapon;
|
||
}
|
||
set
|
||
{
|
||
if (Math.Abs(_splitScaleRaiseWeapon - value) < 0.01f) return;
|
||
_splitScaleRaiseWeapon = value;
|
||
rawAnim.SetFloat(EAnimParamConst.RaiseWeaponScale, _splitScaleRaiseWeapon);
|
||
}
|
||
}
|
||
|
||
public float NORMAL_MOVESPEED = 3f;
|
||
public float LOW_MOVESPEED = 0.6f;
|
||
|
||
public CharacterAnim(Character owner)
|
||
{
|
||
this.owner = owner;
|
||
rawAnim = owner.RawAnimator;
|
||
}
|
||
|
||
public void ResetFloats()
|
||
{
|
||
rawAnim.SetFloat(EAnimParamConst.AttackScaleNormal, _splitScaleNormalShoot);
|
||
rawAnim.SetFloat(EAnimParamConst.ReloadScaleNormal, _splitScaleNormalReload);
|
||
rawAnim.SetFloat(EAnimParamConst.MoveScaleNormal, _splitScaleNormalMove);
|
||
rawAnim.SetFloat(EAnimParamConst.MoveScaleLow, _splitScaleLowMove);
|
||
rawAnim.SetFloat(EAnimParamConst.RaiseWeaponScale, _splitScaleRaiseWeapon);
|
||
|
||
if (owner.weapon.weaponAnim != null && owner.weapon.weaponAnim.rawAnim != null)
|
||
{
|
||
owner.weapon.weaponAnim.rawAnim.SetFloat(EAnimParamConst.AttackScaleNormal, _splitScaleNormalShoot);
|
||
owner.weapon.weaponAnim.rawAnim.SetFloat(EAnimParamConst.ReloadScaleNormal, _splitScaleNormalReload);
|
||
}
|
||
|
||
}
|
||
|
||
public async UniTask Init()
|
||
{
|
||
await _InitAnimInfo();
|
||
ResetAnim();
|
||
}
|
||
|
||
private async UniTask _InitAnimInfo()
|
||
{
|
||
_layerDict = new Dictionary<int, LTAnimLayerInfo>();
|
||
|
||
var fileName = owner.runtimeData.configData.nameId;
|
||
var animInfoPath = string.Format(Constants.ANIMATOR_CONFIG_FORMAT_PATH, fileName);
|
||
var loadAsset = await AssetManager.Instance.LoadAssetAsync<TextAsset>(animInfoPath);
|
||
if (loadAsset == null)
|
||
{
|
||
DebugUtil.LogError("[AnimatorInfoExporter] Load animator info failed: {0}", animInfoPath);
|
||
return;
|
||
}
|
||
var json = loadAsset.text;
|
||
var result = JsonUtility.FromJson<SaveAnimatorData>(json);
|
||
|
||
// 立即释放资源
|
||
AssetManager.Instance.Unload(animInfoPath);
|
||
|
||
var layers = result.layers;
|
||
|
||
// 遍历每个 Layer,获取其中的所有动画状态信息
|
||
for (var i = 0; i < layers.Count; ++i)
|
||
{
|
||
var layer = layers[i];
|
||
GetAllStates(layer, i);
|
||
}
|
||
|
||
}
|
||
|
||
/// <summary>
|
||
/// 该方法需要在动画速度发生改变时进行调用
|
||
/// </summary>
|
||
public void ResetAnim()
|
||
{
|
||
ResetReloadAnim();
|
||
ResetShootAnim();
|
||
ResetRaiseWeaponAnim();
|
||
ResetAttackEndAnim();
|
||
}
|
||
|
||
public void ResetAttackEndAnim()
|
||
{
|
||
var attackEndAnimLength = GetStateLength(EAnimFullState.S_ATTACK_END, EAnimStateIndex.Full);
|
||
var attackEndAnimTime = owner.fightData.attackEndTime;
|
||
var splitScaleAttackEnd = attackEndAnimLength / attackEndAnimTime;
|
||
rawAnim.SetFloat(EAnimParamConst.AttackEndScale, splitScaleAttackEnd);
|
||
}
|
||
|
||
public void ResetRaiseWeaponAnim()
|
||
{
|
||
var raiseTime = owner.runtimeData.fightData.raiseWeaponTime;
|
||
var raiseAnimLength = GetStateLength(EAnimFullState.S_RAISE, EAnimStateIndex.Full);
|
||
splitScaleRaiseWeapon = raiseAnimLength / raiseTime;
|
||
}
|
||
|
||
public void ResetReloadAnim()
|
||
{
|
||
// reload时间
|
||
var reloadTime = owner.fightData.reloadTime;
|
||
var reloadAnimLength = GetStateLength(EAnimFullState.S_RELOAD, EAnimStateIndex.Full);
|
||
splitScaleNormalReload = reloadAnimLength / reloadTime;
|
||
}
|
||
|
||
public void ResetShootAnim()
|
||
{
|
||
// 开枪时间
|
||
var shootTime = owner.fightData.shootCd;
|
||
var shootAnimLength = GetStateLength(EAnimFullState.S_ATTACK, EAnimStateIndex.Full);
|
||
splitScaleNormalShoot = shootAnimLength / shootTime;
|
||
}
|
||
|
||
private void GetAllStates(SaveLayerData stateMachine,
|
||
int layerIndex)
|
||
{
|
||
// 获取 stateMachine 中的所有动画状态信息
|
||
var states = stateMachine.states;
|
||
var newLayer = new LTAnimLayerInfo(layerIndex);
|
||
_layerDict.Add(layerIndex, newLayer);
|
||
// 遍历每个动画状态信息并处理
|
||
foreach (var state in states)
|
||
{
|
||
var newStateInfo = new LTAnimStateInfo();
|
||
newStateInfo.stateName = state.stateName;
|
||
newStateInfo.clipName = state.clipName;
|
||
newStateInfo.clipLength = state.clipLength;
|
||
|
||
newLayer.stateMap.Add(state.stateName, newStateInfo);
|
||
}
|
||
|
||
}
|
||
|
||
public void ViewUpdate(float dt)
|
||
{
|
||
|
||
if (currentFullAnim != targetFullAnim)
|
||
{
|
||
if (currentFullAnim == null || noFade)
|
||
{
|
||
rawAnim.Play(targetFullAnim, EAnimStateIndex.Full, 0);
|
||
}
|
||
else
|
||
{
|
||
rawAnim.CrossFade(targetFullAnim, 0.1f, EAnimStateIndex.Full, 0);
|
||
}
|
||
currentFullAnim = targetFullAnim;
|
||
}
|
||
|
||
if (currentDownAnim != targetDownAnim)
|
||
{
|
||
// TODO: 下半身融合看着比较奇怪,暂时不用
|
||
if (currentDownAnim == null || noFade)
|
||
{
|
||
rawAnim.Play(targetDownAnim, EAnimStateIndex.Down, 0);
|
||
}
|
||
else
|
||
{
|
||
rawAnim.CrossFade(targetDownAnim, 0.05f, EAnimStateIndex.Down, 0);
|
||
}
|
||
currentDownAnim = targetDownAnim;
|
||
}
|
||
}
|
||
|
||
public float GetStateLength(string stateName,
|
||
int layerIndex)
|
||
{
|
||
var layer = _layerDict[layerIndex];
|
||
var stateInfo = layer.stateMap[stateName];
|
||
return stateInfo.clipLength;
|
||
}
|
||
|
||
//public void SetStateSpeed(string stateName, int layerIndex, float speed)
|
||
//{
|
||
// var layer = _layerDict[layerIndex];
|
||
// var stateInfo = layer.stateMap[stateName];
|
||
// stateInfo.rawState.speed = speed;
|
||
//}
|
||
|
||
}
|
||
}
|