From 6732aef384e03b0645580c81d270f2204a2dce95 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C5=A1a=20Ceviel?= Date: Thu, 4 Dec 2025 21:44:11 +0300 Subject: [PATCH] =?UTF-8?q?=D0=9F=D0=BB=D0=B0=D0=B2=D0=BD=D0=BE=D1=81?= =?UTF-8?q?=D1=82=D1=8C=20=D1=8D=D1=82=D0=BE=20=D0=BA=D1=80=D1=83=D1=82?= =?UTF-8?q?=D0=BE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Controller/CustomCharacterController.cs | 161 +++++++++++++----- 1 file changed, 117 insertions(+), 44 deletions(-) diff --git a/Game/CourierOld/Assets/Code/Gameplay/Character/Controller/CustomCharacterController.cs b/Game/CourierOld/Assets/Code/Gameplay/Character/Controller/CustomCharacterController.cs index 5a2ad14..8cbc84a 100644 --- a/Game/CourierOld/Assets/Code/Gameplay/Character/Controller/CustomCharacterController.cs +++ b/Game/CourierOld/Assets/Code/Gameplay/Character/Controller/CustomCharacterController.cs @@ -30,6 +30,14 @@ namespace Code.Gameplay.Character.Controller private Vector3 _originalColliderCenter; private float _originalColliderHeight; private Vector3 _originalFollowPointLocalPosition; + private bool _isEnteringSlide; + private bool _isExitingSlide; + private float _slideTransitionTime; + private float _slideTransitionDuration; + private float _currentColliderHeight; + private Vector3 _currentColliderCenter; + private Vector3 _currentFollowPointLocalPosition; + private bool _wasSlidingLastFrame; // Подсистемы private CharacterInputHandler _inputHandler; @@ -99,16 +107,13 @@ namespace Code.Gameplay.Character.Controller _wallLeanMechanic.SetModel(characterTransform); _wallRunningMechanic.Initialize(motor); - if (_capsuleCollider != null) - { - _originalColliderCenter = _capsuleCollider.center; - _originalColliderHeight = _capsuleCollider.height; - } + _originalColliderCenter = _capsuleCollider.center; + _originalColliderHeight = _capsuleCollider.height; + _originalFollowPointLocalPosition = _cameraFollowPoint.localPosition; - if (_cameraFollowPoint != null) - { - _originalFollowPointLocalPosition = _cameraFollowPoint.localPosition; - } + _currentColliderHeight = _originalColliderHeight; + _currentColliderCenter = _originalColliderCenter; + _currentFollowPointLocalPosition = _originalFollowPointLocalPosition; } // Текущий режим камеры для адаптации поведения @@ -201,29 +206,32 @@ namespace Code.Gameplay.Character.Controller return; } - if (!_slideMechanic.IsSliding) + var wasSliding = _wasSlidingLastFrame; + var isSlidingNow = _slideMechanic.IsSliding; + + if (!isSlidingNow) { _slideMechanic.TryStartSlide(motor, _currentCameraMode, _inputHandler.FirstPersonCameraRotation, _inputHandler.LookInputVector); - - if (_slideMechanic.IsSliding) - { - EnterSlideState(); - } - else - { - ExitSlideState(); - } + isSlidingNow = _slideMechanic.IsSliding; } - else + + switch (isSlidingNow) + { + case true when !wasSliding: + EnterSlideState(); + break; + case false when wasSliding: + ExitSlideState(); + break; + } + + if (isSlidingNow) { _slideMechanic.HandleSlide(ref currentVelocity, deltaTime, motor); - - if (!_slideMechanic.IsSliding) - { - ExitSlideState(); - } } + _wasSlidingLastFrame = isSlidingNow; + // === WALL RUNNING: обработка состояния === if (_wallRunningMechanic.IsWallRunning) { @@ -261,37 +269,100 @@ namespace Code.Gameplay.Character.Controller private void EnterSlideState() { - if (_capsuleCollider) - { - var newHeight = _originalColliderHeight * _characterConfig.slideColliderHeightScale; - - _capsuleCollider.height = newHeight; - - var newCenterY = newHeight * 0.5f - _originalColliderHeight * 0.5f; - _capsuleCollider.center = _originalColliderCenter + Vector3.up * newCenterY; - } - - if (!_cameraFollowPoint) return; - - var offset = Vector3.up * _characterConfig.slideCameraOffsetY; - _cameraFollowPoint.localPosition = _originalFollowPointLocalPosition + offset; + _isEnteringSlide = true; + _isExitingSlide = false; + _slideTransitionTime = 0f; + _slideTransitionDuration = _characterConfig.slideEnterDuration; } private void ExitSlideState() { + _isExitingSlide = true; + _isEnteringSlide = false; + _slideTransitionTime = 0f; + _slideTransitionDuration = _characterConfig.slideExitDuration; + } + + private void UpdateSlideTransition(float deltaTime) + { + if (!_isEnteringSlide && !_isExitingSlide) return; + + _slideTransitionTime += deltaTime; + var t = Mathf.Clamp01(_slideTransitionTime / _slideTransitionDuration); + + t = Mathf.SmoothStep(0f, 1f, t); + + if (_isEnteringSlide) + { + var targetHeight = _originalColliderHeight * _characterConfig.slideColliderHeightScale; + var targetCenterY = targetHeight * 0.5f - _originalColliderHeight * 0.5f; + var targetCenter = _originalColliderCenter + Vector3.up * targetCenterY; + + var targetFollowPos = _originalFollowPointLocalPosition + Vector3.up * _characterConfig.slideCameraOffsetY; + + _currentColliderHeight = Mathf.Lerp(_originalColliderHeight, targetHeight, t); + _currentColliderCenter = Vector3.Lerp(_originalColliderCenter, targetCenter, t); + _currentFollowPointLocalPosition = Vector3.Lerp(_originalFollowPointLocalPosition, targetFollowPos, t); + } + else if (_isExitingSlide) + { + _currentColliderHeight = Mathf.Lerp(_originalColliderHeight * _characterConfig.slideColliderHeightScale, _originalColliderHeight, t); + + var prevHeight = _originalColliderHeight * _characterConfig.slideColliderHeightScale; + var prevCenterY = prevHeight * 0.5f - _originalColliderHeight * 0.5f; + var prevCenter = _originalColliderCenter + Vector3.up * prevCenterY; + + var prevFollowPos = _originalFollowPointLocalPosition + Vector3.up * _characterConfig.slideCameraOffsetY; + + _currentColliderCenter = Vector3.Lerp(prevCenter, _originalColliderCenter, t); + _currentFollowPointLocalPosition = Vector3.Lerp(prevFollowPos, _originalFollowPointLocalPosition, t); + } + if (_capsuleCollider) { - _capsuleCollider.height = _originalColliderHeight; - _capsuleCollider.center = _originalColliderCenter; + _capsuleCollider.height = _currentColliderHeight; + _capsuleCollider.center = _currentColliderCenter; } if (_cameraFollowPoint) { - _cameraFollowPoint.localPosition = _originalFollowPointLocalPosition; + _cameraFollowPoint.localPosition = _currentFollowPointLocalPosition; } + + if (!(t >= 1f)) return; + + if (_isEnteringSlide) + { + _isEnteringSlide = false; + if (_capsuleCollider) + { + _capsuleCollider.height = _originalColliderHeight * _characterConfig.slideColliderHeightScale; + var h = _capsuleCollider.height; + _capsuleCollider.center = _originalColliderCenter + Vector3.up * (h * 0.5f - _originalColliderHeight * 0.5f); + } + if (_cameraFollowPoint) + { + _cameraFollowPoint.localPosition = _originalFollowPointLocalPosition + Vector3.up * _characterConfig.slideCameraOffsetY; + } + } + else if (_isExitingSlide) + { + _isExitingSlide = false; + if (_capsuleCollider) + { + _capsuleCollider.height = _originalColliderHeight; + _capsuleCollider.center = _originalColliderCenter; + } + if (_cameraFollowPoint) + { + _cameraFollowPoint.localPosition = _originalFollowPointLocalPosition; + } + } + + _currentColliderHeight = _capsuleCollider ? _capsuleCollider.height : _originalColliderHeight; + _currentColliderCenter = _capsuleCollider ? _capsuleCollider.center : _originalColliderCenter; + _currentFollowPointLocalPosition = _cameraFollowPoint ? _cameraFollowPoint.localPosition : _originalFollowPointLocalPosition; } - - public void BeforeCharacterUpdate(float deltaTime) { @@ -307,6 +378,8 @@ namespace Code.Gameplay.Character.Controller public void AfterCharacterUpdate(float deltaTime) { + UpdateSlideTransition(deltaTime); + _wallLeanMechanic.Update( _wallRunningMechanic.IsWallRunning, _wallRunningMechanic.GetWallNormal(),