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 { get; set; } public string targetFullAnim { get; set; } public bool noFade = false; public string currentDownAnim { get; private set; } public string currentFullAnim { get; private set; } public readonly Animator rawAnim; private Dictionary _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(); var fileName = owner.runtimeData.configData.nameId; var animInfoPath = string.Format(Constants.ANIMATOR_CONFIG_FORMAT_PATH, fileName); var loadAsset = await AssetManager.Instance.LoadAssetAsync(animInfoPath); if (loadAsset == null) { DebugUtil.LogError("[AnimatorInfoExporter] Load animator info failed: {0}", animInfoPath); return; } var json = loadAsset.text; var result = JsonUtility.FromJson(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); } } /// /// 该方法需要在动画速度发生改变时进行调用 /// 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; if (raiseTime <= 0) { DebugUtil.LogError("配置的 raiseWeaponTime 为 0, 请检查配置"); return; } var raiseAnimLength = GetStateLength(EAnimFullState.S_RAISE, EAnimStateIndex.Full); splitScaleRaiseWeapon = raiseAnimLength / raiseTime; } public void ResetReloadAnim() { // reload时间 var reloadTime = owner.fightData.reloadTime; if (reloadTime <= 0) { DebugUtil.LogError("配置的 reloadTime 为 0, 请检查配置"); return; } var reloadAnimLength = GetStateLength(EAnimFullState.S_RELOAD, EAnimStateIndex.Full); splitScaleNormalReload = reloadAnimLength / reloadTime; } public void ResetShootAnim() { // 开枪时间 var shootTime = owner.fightData.shootCd; if (shootTime <= 0) { DebugUtil.LogError("配置的 shootCd 为 0, 请检查配置"); return; } 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; //} } }