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 targetUpAnim; public string targetDownAnim; public string targetFullAnim; public bool noFade = false; public string currentUpAnim { get; private set; } public string currentDownAnim { get; private set; } public string currentFullAnim { get; private set; } public readonly Animator rawAnim; private bool _lastIsFullControl = false; public bool isFullControl = false; 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 _splitScaleLowShoot = 1; public float splitScaleLowShoot { get { return _splitScaleLowShoot; } set { if (Math.Abs(_splitScaleLowShoot - value) < 0.01f) return; _splitScaleLowShoot = value; rawAnim.SetFloat(EAnimParamConst.AttackScaleLow, _splitScaleLowShoot); if (owner.weapon != null && owner.weapon.weaponAnim.rawAnim != null) { owner.weapon.weaponAnim.rawAnim.SetFloat(EAnimParamConst.AttackScaleLow, _splitScaleLowShoot); } } } 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 _splitScaleLowReload = 1; public float splitScaleLowReload { get { return _splitScaleLowReload; } set { if (Math.Abs(_splitScaleLowReload - value) < 0.01f) return; _splitScaleLowReload = value; rawAnim.SetFloat(EAnimParamConst.ReloadScaleLow, _splitScaleLowReload); if (owner.weapon != null && owner.weapon.weaponAnim.rawAnim != null) { owner.weapon.weaponAnim.rawAnim.SetFloat(EAnimParamConst.ReloadScaleLow, _splitScaleLowReload); } } } 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); } } public float NORMAL_MOVESPEED = 3f; public float LOW_MOVESPEED = 0.6f; public CharacterAnim(Character owner) { this.owner = owner; rawAnim = owner.RawAnimator; // var animatorInst = Object.Instantiate(rawAnim.runtimeAnimatorController); // var overrideController = animatorInst as AnimatorOverrideController; // if (overrideController != null) // { // // 把基础animator也clone一份 // var baseController = overrideController.runtimeAnimatorController; // var cloneController = Object.Instantiate(baseController); // overrideController.runtimeAnimatorController = cloneController; // } // rawAnim.runtimeAnimatorController = animatorInst; _lastIsFullControl = false; isFullControl = false; rawAnim.SetLayerWeight(EAnimStateIndex.Full, 0); rawAnim.SetLayerWeight(EAnimStateIndex.Up, 1); rawAnim.SetLayerWeight(EAnimStateIndex.Down, 1); } public void ResetFloats() { rawAnim.SetFloat(EAnimParamConst.AttackScaleNormal, _splitScaleNormalShoot); rawAnim.SetFloat(EAnimParamConst.AttackScaleLow, _splitScaleLowShoot); rawAnim.SetFloat(EAnimParamConst.ReloadScaleNormal, _splitScaleNormalReload); rawAnim.SetFloat(EAnimParamConst.ReloadScaleLow, _splitScaleLowReload); rawAnim.SetFloat(EAnimParamConst.MoveScaleNormal, _splitScaleNormalMove); rawAnim.SetFloat(EAnimParamConst.MoveScaleLow, _splitScaleLowMove); if (owner.weapon.weaponAnim != null && owner.weapon.weaponAnim.rawAnim != null) { owner.weapon.weaponAnim.rawAnim.SetFloat(EAnimParamConst.AttackScaleNormal, _splitScaleNormalShoot); owner.weapon.weaponAnim.rawAnim.SetFloat(EAnimParamConst.AttackScaleLow, _splitScaleLowShoot); owner.weapon.weaponAnim.rawAnim.SetFloat(EAnimParamConst.ReloadScaleNormal, _splitScaleNormalReload); owner.weapon.weaponAnim.rawAnim.SetFloat(EAnimParamConst.ReloadScaleLow, _splitScaleLowReload); } } 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(); } public void ResetReloadAnim() { // reload时间 var reloadTime = owner.fightData.reloadTime; var reloadAnimLength = GetStateLength(EAnimUpState.S_RELOAD, EAnimStateIndex.Up); splitScaleNormalReload = reloadAnimLength / reloadTime; // rawAnim.SetFloat(EAnimParamConst.ReloadScaleNormal, splitScaleNormalReload); var cReloadAnimLength = GetStateLength(EAnimUpState.S_C_RELOAD, EAnimStateIndex.Up); splitScaleLowReload = cReloadAnimLength / reloadTime; // rawAnim.SetFloat(EAnimParamConst.ReloadScaleLow, splitScaleLowReload); } public void ResetShootAnim() { // 开枪时间 var shootTime = owner.fightData.shootCd; var shootAnimLength = GetStateLength(EAnimUpState.S_ATTACK, EAnimStateIndex.Up); splitScaleNormalShoot = shootAnimLength / shootTime; // rawAnim.SetFloat(EAnimParamConst.AttackScaleNormal, splitScaleNormalShoot); var cShootAnimLength = GetStateLength(EAnimUpState.S_C_ATTACK, EAnimStateIndex.Up); splitScaleLowShoot = cShootAnimLength / shootTime; // rawAnim.SetFloat(EAnimParamConst.AttackScaleLow, splitScaleLowShoot); } 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 (isFullControl != _lastIsFullControl) { // 控制状态发生改变 if (isFullControl) { rawAnim.SetLayerWeight(EAnimStateIndex.Full, 1); rawAnim.SetLayerWeight(EAnimStateIndex.Up, 0); rawAnim.SetLayerWeight(EAnimStateIndex.Down, 0); } else { rawAnim.SetLayerWeight(EAnimStateIndex.Full, 0); rawAnim.SetLayerWeight(EAnimStateIndex.Up, 1); rawAnim.SetLayerWeight(EAnimStateIndex.Down, 1); } _lastIsFullControl = isFullControl; currentDownAnim = null; currentUpAnim = null; currentFullAnim = null; } 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 (currentUpAnim != targetUpAnim) { if (currentUpAnim == null || noFade) { rawAnim.Play(targetUpAnim, EAnimStateIndex.Up, 0); } else { rawAnim.CrossFade(targetUpAnim, 0.1f, EAnimStateIndex.Up, 0); } currentUpAnim = targetUpAnim; } 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; //} } }