From dbabd847c11f544ab273e525b790f5c75af3d284 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C5=A1a=20Ceviel?= Date: Wed, 12 Nov 2025 20:04:06 +0300 Subject: [PATCH] bugfix no 1 --- .../Controller/Abilities/WallLeanMechanic.cs | 51 ++++++++++++++++--- 1 file changed, 43 insertions(+), 8 deletions(-) diff --git a/Game/CourierOld/Assets/Code/Gameplay/Character/Controller/Abilities/WallLeanMechanic.cs b/Game/CourierOld/Assets/Code/Gameplay/Character/Controller/Abilities/WallLeanMechanic.cs index ffebb98..3b3296e 100644 --- a/Game/CourierOld/Assets/Code/Gameplay/Character/Controller/Abilities/WallLeanMechanic.cs +++ b/Game/CourierOld/Assets/Code/Gameplay/Character/Controller/Abilities/WallLeanMechanic.cs @@ -19,6 +19,10 @@ namespace Code.Gameplay.Character.Controller.Abilities private float _leanFactor; private float _leanSign; private Vector3 _leanDirection; + + private Vector3 _lastWallContactPoint; + private bool _isLeaningOnWall; + private const float WallProximityThreshold = 0.6f; public WallLeanMechanic(float maxLeanAngle, float leanSharpness, float heightScale) { @@ -36,9 +40,16 @@ namespace Code.Gameplay.Character.Controller.Abilities // Вызывается из OnMovementHit public void OnWallContact(KinematicCharacterMotor motor, Vector3 wallNormal, float contactHeight) { + // Только если это действительно стена (не пол/потолок) + var dotWithUp = Vector3.Dot(wallNormal, motor.CharacterUp); + if (Mathf.Abs(dotWithUp) > 0.7f) // ~45°, можно настроить + return; + _lastWallNormal = wallNormal; _lastWallContactHeight = contactHeight; - + _lastWallContactPoint = motor.TransientPosition; + + // Пересчитываем направление наклона _leanDirection = -_lastWallNormal; _leanDirection = Vector3.ProjectOnPlane(_leanDirection, motor.CharacterUp).normalized; @@ -76,6 +87,8 @@ namespace Code.Gameplay.Character.Controller.Abilities break; } } + + _isLeaningOnWall = true; } // Обновление каждый кадр @@ -84,14 +97,35 @@ namespace Code.Gameplay.Character.Controller.Abilities if (!_characterTransform) return; var isGrounded = motor.GroundingStatus.IsStableOnGround; + var currentPosition = motor.TransientPosition; - if (!isGrounded) + var isStillNearWall = false; + if (_isLeaningOnWall && _lastWallNormal != Vector3.zero) { - var heightDelta = motor.TransientPosition.y - _lastWallContactHeight; - var targetLeanFactor = Mathf.Clamp01(heightDelta * _heightScale); - _leanFactor = Mathf.Lerp(_leanFactor, targetLeanFactor, 1f - Mathf.Exp(-_leanSharpness * deltaTime)); + var toWall = currentPosition - _lastWallContactPoint; + var distanceToWallPlane = Mathf.Abs(Vector3.Dot(toWall, _lastWallNormal)); + isStillNearWall = distanceToWallPlane <= WallProximityThreshold; } - else + + if (_isLeaningOnWall) + { + switch (isGrounded) + { + case true when !isStillNearWall: + case false when !isStillNearWall: + _isLeaningOnWall = false; + break; + default: + { + var heightDelta = currentPosition.y - _lastWallContactHeight; + var targetLeanFactor = Mathf.Clamp01(heightDelta * _heightScale); + _leanFactor = Mathf.Lerp(_leanFactor, targetLeanFactor, 1f - Mathf.Exp(-_leanSharpness * deltaTime)); + break; + } + } + } + + if (!_isLeaningOnWall) { _leanFactor = Mathf.Lerp(_leanFactor, 0f, 1f - Mathf.Exp(-_leanSharpness * deltaTime)); } @@ -108,9 +142,10 @@ namespace Code.Gameplay.Character.Controller.Abilities } if (_leanDirection.sqrMagnitude < 0.01f) return; - + var leanAngle = _leanSign * _leanFactor * _maxLeanAngle; - var leanRotation = Quaternion.AngleAxis(leanAngle, Vector3.Cross(motor.CharacterUp, _leanDirection)); + var leanAxis = Vector3.Cross(motor.CharacterUp, _leanDirection); + var leanRotation = Quaternion.AngleAxis(leanAngle, leanAxis); _characterTransform.localRotation = leanRotation; } }