Files
Net.Like.Xue.Tokyo/Packages-Local/Com.Project.B.Unity/CharacterAnimation/PlayerAnimancerController.cs
2025-06-24 23:49:13 +08:00

497 lines
22 KiB
C#

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<float2> _idleAnimation;
private readonly IWrapper<float2> _walkAnimation;
private readonly IWrapper<float2> _crouchedAnimation;
private readonly IWrapper<float2> _knockedAnimation;
private readonly IWrapper<float> _runAnimation;
private readonly IWrapper<float> _sprintAnimation;
private readonly IEntity _entity;
private readonly IWrapper<float2> _idleToWalkWrapper;
private readonly IWrapper<float2> _idleTurnAnimation;
private readonly IWrapper<float2> _walkToIdleAnimation;
private readonly IWrapper<float> _ladderAnimation;
private readonly IWrapper<float> _climbingAnimation;
private readonly IWrapper<float2> _parachuteAnimation;
private readonly IWrapper<float> _swimmingAnimation;
private readonly IHealthService _healthService;
private readonly ILogger<PlayerAnimancerController> _logger;
private CancellationTokenSource _transitionCts;
public PlayerAnimancerController(AnimancerComponent animancerComponent, ICharacterController characterController, IPlayerAnimationFactory playerAnimationFactory, ITicker ticker, IEntity entity, GameObject gameObject, IPlayerWeaponInventory weaponInventory, IHealthService healthService, ILogger<PlayerAnimancerController> 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<ICharacterStateIdle>();
}
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<Vector2>,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<Vector2>,fadeDuration).Time = 0;
break;
case ICharacterStateCrouched:
AnimancerComponent.Layers[Layer].Play(_crouchedAnimation.Obj as MixerState<Vector2>,fadeDuration).Time = 0;
break;
case ICharacterStateRun:
AnimancerComponent.Layers[Layer].Play(_runAnimation.Obj as MixerState<float>,fadeDuration).Time = 0;
if (_playerCharacterController.AllowTpsCamera.Allow)
{
_runAnimation.Value = 1;
}
break;
case ICharacterSprint:
AnimancerComponent.Layers[Layer].Play(_sprintAnimation.Obj as MixerState<float>,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<Vector2>,
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);
}
}
}