using System; using System.Collections; using System.Collections.Concurrent; using System.Collections.Generic; using System.Linq; using System.Threading; using Animancer; using BITKit; using BITKit.Entities; using BITKit.Pool; using Cysharp.Threading.Tasks; using Microsoft.Extensions.Logging; using Net.Project.B.Health; using Net.Project.B.Inventory; using NodeCanvas.Framework; using Project.B.Animation; using Project.B.CharacterController; using Unity.Mathematics; using UnityEngine; using Object = UnityEngine.Object; namespace Project.B.Animation { public class PlayerAnimancerController:IDisposable { public int Layer; public AnimancerComponent AnimancerComponent; private readonly Transform _transform; private readonly GameObject _gameObject; private readonly IPlayerWeaponInventory _weaponInventory; private readonly IPlayerCharacterController _playerCharacterController; private readonly ICharacterController _characterController; private readonly IHumanoidTransitionAnimationFactory _transitionAnimationFactory; private readonly IPlayerAnimationFactory _playerAnimationFactory; private readonly ITicker _ticker; private readonly IWrapper _idleAnimation; private readonly IWrapper _walkAnimation; private readonly IWrapper _crouchedAnimation; private readonly IWrapper _knockedAnimation; private readonly IWrapper _runAnimation; private readonly IWrapper _sprintAnimation; private readonly IEntity _entity; private readonly IWrapper _idleToWalkWrapper; private readonly IWrapper _idleTurnAnimation; private readonly IWrapper _walkToIdleAnimation; private readonly IWrapper _ladderAnimation; private readonly IWrapper _climbingAnimation; private readonly IWrapper _parachuteAnimation; private readonly IWrapper _swimmingAnimation; private readonly IHealthService _healthService; private readonly ILogger _logger; private CancellationTokenSource _transitionCts; public PlayerAnimancerController(AnimancerComponent animancerComponent, ICharacterController characterController, IPlayerAnimationFactory playerAnimationFactory, ITicker ticker, IEntity entity, GameObject gameObject, IPlayerWeaponInventory weaponInventory, IHealthService healthService, ILogger logger, IHumanoidTransitionAnimationFactory transitionAnimationFactory, IPlayerCharacterController playerCharacterController, Transform transform) { AnimancerComponent = animancerComponent; _characterController = characterController; _playerAnimationFactory = playerAnimationFactory; _ticker = ticker; _entity = entity; _gameObject = gameObject; _weaponInventory = weaponInventory; _healthService = healthService; _logger = logger; _transitionAnimationFactory = transitionAnimationFactory; _playerCharacterController = playerCharacterController; _transform = transform; _idleAnimation = playerAnimationFactory.CreateIdleAnimation(); _walkAnimation = playerAnimationFactory.CreateWalkAnimation(); _crouchedAnimation = playerAnimationFactory.CreateCrouchedAnimation(); _knockedAnimation = playerAnimationFactory.CreateKnockedAnimation(); _runAnimation = playerAnimationFactory.CreateRunAnimation(); _sprintAnimation = playerAnimationFactory.CreateSprintAnimation(); _ladderAnimation = _playerAnimationFactory.CreateLadderAnimation(); _climbingAnimation = _playerAnimationFactory.CreateClimbingAnimation(); _idleToWalkWrapper = transitionAnimationFactory.CreateIdleToWalk(); _idleTurnAnimation = transitionAnimationFactory.CreateIdleTurn(); _walkToIdleAnimation = transitionAnimationFactory.CreateWalkToIdle(); _parachuteAnimation = playerAnimationFactory.CreateParachuteAnimation(); _swimmingAnimation = playerAnimationFactory.CreateSwimmingAnimation(); _characterController.OnStateChanged += OnStateChanged; ticker.Add(OnTick); _healthService.OnHealthChanged += OnHealthChanged; _playerCharacterController.AllowTpsCamera.AddListener(OnTPS); // _logger.LogInformation("已创建Animancer控制器"); } private void OnTPS(bool obj) { OnStateChanged(_characterController.CurrentState,_characterController.CurrentState); } private void OnHealthChanged(int arg1, int arg2, int arg3, object arg4) { if(arg1!=_entity.Id)return; if (arg3 >= 0) { OnStateChanged(null, _characterController.CurrentState); } } private ICharacterState _currentState; private void OnTick(float delta) { var velocity = _characterController.SelfVelocity; if (_playerCharacterController.AllowTpsCamera.Allow) { velocity = (Quaternion)_characterController.ViewRotation * _playerCharacterController.MoveInput; velocity = _transform.InverseTransformDirection(velocity); } AnimancerComponent.Layers[Layer].Speed = _characterController.CurrentState switch { (ICharacterStateWalk or ICharacterStateRun or ICharacterSprint) when _characterController.IsGrounded is false=>0.32f, _ => 1 }; switch (_characterController.CurrentState) { case ICharacterStateWalk: _walkAnimation.Value =math.lerp(_walkAnimation.Value,new Vector2(velocity.x, velocity.z),16*Time.deltaTime); break; case ICharacterStateCrouched: _crouchedAnimation.Value =math.lerp(_crouchedAnimation.Value,new Vector2(velocity.x, velocity.z),16*Time.deltaTime); break; case ICharacterStateRun: { if (_characterController.CurrentState is ICharacterStateData data) { _runAnimation.Value = _playerCharacterController.AllowTpsCamera.Allow ? 1 : _characterController.SelfVelocity.z / data.BaseSpeed; } } break; case ICharacterSprint: { if (_characterController.CurrentState is ICharacterStateData data) { _sprintAnimation.Value =_playerCharacterController.AllowTpsCamera.Allow ? 1 : _characterController.SelfVelocity.z / data.BaseSpeed; } } break; case ICharacterLadder: { _ladderAnimation.Value = Mathf.Lerp( _ladderAnimation.Value , _playerCharacterController.MoveInput.z,2*delta); } break; case ICharacterKnocked: _knockedAnimation.Value = new Vector2(velocity.x, velocity.z); break; case ICharacterStateClimb: { _climbingAnimation.Value = Mathf.Lerp(_climbingAnimation.Value, _playerCharacterController.MoveInput.x, 2 * delta); } break; case ICharacterParachute: { var v = _playerCharacterController.CharacterController.SelfVelocity; _parachuteAnimation.Value = math.lerp(_parachuteAnimation.Value,new(v.x,v.y) , 2 * delta); } break; case ICharacterSwimming: { var v = _playerCharacterController.CharacterController.SelfVelocity; _swimmingAnimation.Value =math.clamp(math.lerp(_swimmingAnimation.Value,MathV.GetLength(v), 2 * delta),0,1) ; } break; } if (_playerCharacterController.AllowTpsCamera.Allow ) { switch (_characterController.CurrentState) { case ICharacterStateWalk: case ICharacterStateRun: case ICharacterSprint: { if(((Vector3)velocity).GetLength()<0.1f)break; var targetRotation =Quaternion.LookRotation( Vector3.ProjectOnPlane((Quaternion)_characterController.ViewRotation * _playerCharacterController.MoveInput, Vector3.up)); var currentRotation = _characterController.Rotation; _characterController.Rotation = Quaternion.Lerp(currentRotation, targetRotation, _transitionCts is {IsCancellationRequested:true} ? 2 * delta : delta); } break; } } } private async void OnStateChanged(ICharacterState arg1, ICharacterState arg2) { _playerCharacterController.ForceRootMotion.SetElements(this,_playerCharacterController.AllowTpsCamera.Allow && arg2 switch { ICharacterStateWalk=>true, ICharacterStateRun=>true, ICharacterStateIdle=>true, ICharacterSprint=>true, _=>false, } && _playerCharacterController.CharacterController.IsGrounded); if(Equals(_currentState,arg2))return; _transitionCts?.Cancel(); _transitionCts = new CancellationTokenSource(); if (arg2 is null) { AnimancerComponent.Layers[Layer].Stop(); return; } _playerCharacterController.ForceRootMotion.SetElements(15616, arg2 switch { ICharacterLadder=>true, ICharacterStateClimb=>true, _=>false, }); var velocity = _characterController.SelfVelocity; _currentState = arg2; var fadeDuration = (arg1, arg2) switch { (ICharacterStateStepUp,_)=>0.32f, (ICharacterStateClimb,_)=>0.32f, (ICharacterSliding,not ICharacterSliding)=>0.32f, _ => 0.1f }; if (_playerCharacterController.AllowTpsCamera.Allow) { switch (arg1,arg2) { case (ICharacterStateIdle,ICharacterStateWalk): var dir = (Quaternion)_characterController.ViewRotation * _playerCharacterController.MoveInput; var direction = (Vector3)_characterController.Position + dir; direction = Vector3.ProjectOnPlane(_transform.InverseTransformPoint(direction), Vector3.up) ; _idleToWalkWrapper.Value = new(direction.x, direction.z); try { using var wait = _playerCharacterController.ForceRootMotion.GetHandle(); var walkState = AnimancerComponent.Layers[Layer].Play(_idleToWalkWrapper.Obj as AnimancerState, 0.2f); // walkState.Time = 0.2f; await walkState.WithCancellation(_transitionCts.Token); } catch (OperationCanceledException) { return; } break; case (ICharacterStateRun or ICharacterSprint, ICharacterStateIdle): { try { await AnimancerComponent.Layers[Layer].Play(_transitionAnimationFactory.CreateRunToIdle() as AnimationClip); } catch (OperationCanceledException) { return; } } break; case (ICharacterStateWalk, ICharacterStateIdle): { try { _walkToIdleAnimation.Value = new(0, 1); await AnimancerComponent.Layers[Layer].Play(_walkToIdleAnimation.Obj as AnimancerState, 0.2f).WithCancellation(_transitionCts.Token); } catch (OperationCanceledException) { return; } } break; } } switch (arg1,arg2) { case (ICharacterKnocked, _): { try { using var wait = _playerCharacterController.ForceRootMotion.GetHandle(); using var disable = _playerCharacterController.DisableStateTransition.GetHandle(); var walkState = AnimancerComponent.Layers[Layer] .Play(_playerAnimationFactory.CreateRevivedAnimation() as AnimationClip, 0.2f); // walkState.Time = 0.2f; await walkState.WithCancellation(_transitionCts.Token); } catch (OperationCanceledException) { return; } } break; case (ICharacterStateClimb, ICharacterStateStepUp): { using var waiter = _playerCharacterController.ForceRootMotion.GetHandle(); try { await AnimancerComponent.Layers[Layer] .Play(_playerAnimationFactory.CreateClimbUpAnimation() as AnimationClip).WithCancellation(_transitionCts.Token); _characterController.TransitionState(); } catch (OperationCanceledException) { } return; } case (_, ICharacterLadder): { try { await AnimancerComponent.Layers[Layer] .Play(_playerAnimationFactory.CreateLadderEnterAnimation() as AnimationClip, 0.2f) .WithCancellation(_transitionCts.Token); await AnimancerComponent.Layers[Layer].Play(_ladderAnimation.Obj as AnimancerState).WithCancellation(_transitionCts.Token); } catch (OperationCanceledException) { } } return; case (ICharacterLadder ladder,ICharacterStateIdle): { using var c = _playerCharacterController.DisableCollision.GetHandle(); using var wait = _playerCharacterController.ForceRootMotion.GetHandle(); using var disable = _playerCharacterController.DisableStateTransition.GetHandle(); try { await AnimancerComponent.Layers[Layer] .Play(_playerAnimationFactory.CreateLadderExitAnimation() as AnimationClip).WithCancellation(_transitionCts.Token); } catch (OperationCanceledException) { return; } } break; } if(_transitionCts.IsCancellationRequested)return; switch (arg2) { case ICharacterStateIdle: AnimancerComponent.Layers[Layer].Play(_idleAnimation.Obj as MixerState,fadeDuration).Time = 0; if (_playerCharacterController.AllowTpsCamera.Allow) { _idleAnimation.Value = default; } else { _idleAnimation.Value = MathV.GetLength(velocity)>3 ? new Vector2(velocity.x, velocity.z) : default(float2); } break; case ICharacterStateWalk: AnimancerComponent.Layers[Layer].Play(_walkAnimation.Obj as MixerState,fadeDuration).Time = 0; break; case ICharacterStateCrouched: AnimancerComponent.Layers[Layer].Play(_crouchedAnimation.Obj as MixerState,fadeDuration).Time = 0; break; case ICharacterStateRun: AnimancerComponent.Layers[Layer].Play(_runAnimation.Obj as MixerState,fadeDuration).Time = 0; if (_playerCharacterController.AllowTpsCamera.Allow) { _runAnimation.Value = 1; } break; case ICharacterSprint: AnimancerComponent.Layers[Layer].Play(_sprintAnimation.Obj as MixerState,fadeDuration).Time = 0; if (_playerCharacterController.AllowTpsCamera.Allow) { _sprintAnimation.Value = 1; } break; case ICharacterStateStepUp: AnimancerComponent.Layers[Layer].Play(_playerAnimationFactory.CreateStepUpAnimation() as AnimationClip,fadeDuration).Time=0; break; case ICharacterSliding: AnimancerComponent.Layers[Layer].Play( _playerAnimationFactory.CreateSlidingAnimation() as AnimationClip,fadeDuration); break; case ICharacterStateClimb: try { await AnimancerComponent.Layers[Layer].Play(_playerAnimationFactory.CreateClimbAnimation() as AnimationClip,fadeDuration).WithCancellation(_transitionCts.Token); AnimancerComponent.Layers[Layer].Play(_climbingAnimation.Obj as AnimancerState); } catch (OperationCanceledException) { return; } break; case ICharacterKnocked: { try { await AnimancerComponent.Layers[Layer].Play( _playerAnimationFactory.CreateKnockingAnimation() as AnimationClip, fadeDuration) .WithCancellation(_transitionCts.Token); AnimancerComponent.Layers[Layer].Play(_knockedAnimation.Obj as MixerState, fadeDuration); } catch (OperationCanceledException) { return; } } break; case ICharacterSeating: AnimancerComponent.Layers[Layer].Play(_playerAnimationFactory.CreateSeatAnimation() as AnimationClip,fadeDuration); break; case ICharacterParachute: try { await AnimancerComponent.Layers[Layer].Play(_playerAnimationFactory.CreateOpenParachuteAnimation() as AnimationClip,fadeDuration).WithCancellation(_transitionCts.Token); AnimancerComponent.Layers[Layer].Play(_parachuteAnimation.Obj as AnimancerState, fadeDuration); } catch (OperationCanceledException) { return; } break; case ICharacterFreeFall: AnimancerComponent.Layers[Layer].Play(_playerAnimationFactory.CreateFreeFallAnimation() as AnimationClip,fadeDuration); break; case ICharacterSwimming: AnimancerComponent.Layers[Layer].Play(_swimmingAnimation.Obj as AnimancerState,fadeDuration); break; case ICharacterStateVault: AnimancerComponent.Layers[Layer].Play(_playerAnimationFactory.CreateVaultAnimation() as AnimationClip,fadeDuration).Time=0; break; } _transitionCts.Cancel(); } public void Dispose() { _transitionCts?.Cancel(); _playerCharacterController.AllowTpsCamera.RemoveListener(OnTPS); _characterController.OnStateChanged -= OnStateChanged; _healthService.OnHealthChanged -= OnHealthChanged; _ticker.Remove(OnTick); } } }