using System; using System.Collections; using System.Collections.Generic; using BITKit; using BITKit.Pool; using Net.BITKit.VFX; using UnityEngine; namespace Project.B.CharacterController { public class PlayerFootstepController:IDisposable { private readonly IPoolService _poolService; private readonly VFXService _vfxService; private readonly ICharacterController _characterController; private readonly ITicker _ticker; private readonly Animator _animator; private readonly ValidHandle _isBusy = new(); private readonly IntervalUpdate _intervalUpdate = new(0.32f); private Transform _leftFoot; private Transform _rightFoot; private readonly List _tags = new() { "footstep" }; public PlayerFootstepController(ICharacterController characterController, ITicker ticker, VFXService vfxService, IPoolService poolService, Animator animator) { _characterController = characterController; _ticker = ticker; _vfxService = vfxService; _poolService = poolService; _animator = animator; _ticker.Add(OnTick); _characterController.OnStateChanged += OnStateChanged; } private void OnStateChanged(ICharacterState arg1, ICharacterState arg2) { _intervalUpdate.Interval = 1f / arg2 switch { ICharacterSprint=>7, ICharacterStateRun=>5, _ =>3 }; _intervalUpdate.Reset(); } private async void OnTick(float obj) { if(_isBusy.Allow)return; if(_intervalUpdate.AllowUpdate is false)return; using var wait = _isBusy.GetHandle(); if(_characterController.IsGrounded is false)return; Vector3 planerVelocity = _characterController.Velocity; planerVelocity.y = 0; if(planerVelocity.GetLength()<2)return; var vfx = _vfxService.GetPrefab(_tags).gameObject; if(!vfx)return; vfx =await _poolService.Spawn(vfx.name, vfx); if (!_leftFoot) { _leftFoot = _animator.GetBoneTransform(HumanBodyBones.LeftFoot); } if (!_rightFoot) { _rightFoot = _animator.GetBoneTransform(HumanBodyBones.RightFoot); } if (_leftFoot && _rightFoot) { vfx.transform.position = _leftFoot.position.y < _rightFoot.position.y ? _leftFoot.position : _rightFoot.position; } else { vfx.transform.position = _characterController.Position; } } public void Dispose() { _ticker.Remove(OnTick); } } }