From 4c16a63abd69ea6fe1c31ecc59dcc5258a75712f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C5=A1a=20Ceviel?= Date: Thu, 4 Dec 2025 17:38:45 +0300 Subject: [PATCH] =?UTF-8?q?=D1=8F=20=D0=BA=D1=81=D0=B8=D1=8C=D0=BA=D0=B0?= =?UTF-8?q?=20:3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Abilities/WallRunningMechanic.cs | 181 +++++++----------- 1 file changed, 71 insertions(+), 110 deletions(-) diff --git a/Game/CourierOld/Assets/Code/Gameplay/Character/Controller/Abilities/WallRunningMechanic.cs b/Game/CourierOld/Assets/Code/Gameplay/Character/Controller/Abilities/WallRunningMechanic.cs index 975bf2e..41d47f6 100644 --- a/Game/CourierOld/Assets/Code/Gameplay/Character/Controller/Abilities/WallRunningMechanic.cs +++ b/Game/CourierOld/Assets/Code/Gameplay/Character/Controller/Abilities/WallRunningMechanic.cs @@ -7,14 +7,13 @@ namespace Code.Gameplay.Character.Controller.Abilities { public class WallRunningMechanic { - public float MaxWallRunTime = 1.75f; - public float WallRunSpeed = 8.0f; - public float WallRunAcceleration = 25.0f; - public float WallRunGravityScale = 0.25f; - public float WallDetachImpulse = 7.0f; - public float WallContactAngleThreshold = 45.0f; + private readonly float _maxWallRunTime; + private readonly float _wallRunSpeed; + private readonly float _wallRunAcceleration; + private readonly float _wallRunGravityScale; + private readonly float _wallDetachImpulse; + private readonly float _wallContactAngleThreshold; - private bool _isWallRunning; private float _wallRunTimer; private Vector3 _wallNormal; private Vector3 _wallTangentRight; @@ -24,15 +23,12 @@ namespace Code.Gameplay.Character.Controller.Abilities private float _surfaceAngleCos; private bool _canWallRun; - public float WallContactHeight { get; private set; } - - public Vector3 WallRunStartForward { get; private set; } private KinematicCharacterMotor _motor; private CharacterInputHandler _inputHandler; - public bool IsWallRunning => _isWallRunning; - + public bool IsWallRunning { get; private set; } + public WallRunningMechanic( float maxWallRunTime, float wallRunSpeed, @@ -41,52 +37,44 @@ namespace Code.Gameplay.Character.Controller.Abilities float wallDetachImpulse, float wallContactAngleThreshold) { - MaxWallRunTime = maxWallRunTime; - WallRunSpeed = wallRunSpeed; - WallRunAcceleration = wallRunAcceleration; - WallRunGravityScale = wallRunGravityScale; - WallDetachImpulse = wallDetachImpulse; - WallContactAngleThreshold = wallContactAngleThreshold; + _maxWallRunTime = maxWallRunTime; + _wallRunSpeed = wallRunSpeed; + _wallRunAcceleration = wallRunAcceleration; + _wallRunGravityScale = wallRunGravityScale; + _wallDetachImpulse = wallDetachImpulse; + _wallContactAngleThreshold = wallContactAngleThreshold; } public void Initialize(KinematicCharacterMotor motor, CharacterInputHandler inputHandler) { _motor = motor; _inputHandler = inputHandler; - _surfaceAngleCos = Mathf.Cos(Mathf.Deg2Rad * WallContactAngleThreshold); - } - - public void Reset() - { - _isWallRunning = false; - _wallRunTimer = 0f; - _wallNormal = Vector3.zero; + _surfaceAngleCos = Mathf.Cos(Mathf.Deg2Rad * _wallContactAngleThreshold); } public void Tick(float deltaTime) { - if (_isWallRunning) + if (!IsWallRunning) return; + + _wallRunTimer += deltaTime; + if (_wallRunTimer > _maxWallRunTime) { - _wallRunTimer += deltaTime; - if (_wallRunTimer > MaxWallRunTime) - { - DetachFromWall(false); - } + DetachFromWall(false); } } public bool TryStartWallRun(Vector3 hitNormal, Vector3 hitPoint) { - if (_isWallRunning) return false; + if (IsWallRunning) return false; - float dotWithUp = Vector3.Dot(hitNormal, _motor.CharacterUp); - bool isWall = Mathf.Abs(dotWithUp) < _surfaceAngleCos; + var dotWithUp = Vector3.Dot(hitNormal, _motor.CharacterUp); + var isWall = Mathf.Abs(dotWithUp) < _surfaceAngleCos; if (!isWall) return false; if (_motor.GroundingStatus.IsStableOnGround) return false; - float velocityIntoWall = Vector3.Dot(_motor.Velocity, -hitNormal); + var velocityIntoWall = Vector3.Dot(_motor.Velocity, -hitNormal); if (velocityIntoWall < 1f) return false; StartWallRun(hitNormal, hitPoint); @@ -95,13 +83,11 @@ namespace Code.Gameplay.Character.Controller.Abilities private void StartWallRun(Vector3 wallNormal, Vector3 contactPoint) { - _isWallRunning = true; + IsWallRunning = true; _wallRunTimer = 0f; _wallNormal = wallNormal.normalized; _wallContactPoint = contactPoint; - WallContactHeight = contactPoint.y; - //_wallTangentUp = Vector3.ProjectOnPlane(_motor.CharacterUp, _wallNormal).normalized; if (_wallTangentUp.sqrMagnitude < 0.01f) _wallTangentUp = Vector3.up; _wallTangentRight = Vector3.Cross(_wallNormal, _wallTangentUp).normalized; @@ -109,43 +95,42 @@ namespace Code.Gameplay.Character.Controller.Abilities _wallTangentUp = Vector3.Cross(_wallTangentRight, _wallNormal).normalized; if (Vector3.Dot(_wallTangentUp, Vector3.up) < 0) _wallTangentUp = -_wallTangentUp; - - WallRunStartForward = _motor.CharacterForward; + _motor.ForceUnground(); } public void HandleWallRun(ref Vector3 currentVelocity, CharacterInputs inputs, float deltaTime) { - if (!_isWallRunning) return; + if (!IsWallRunning) return; if (!IsWallStillPresent()) { DetachFromWall(false); return; } - Vector3 moveInputWorld = _inputHandler.MoveInputVector; - Vector3 moveInWallPlane = Vector3.ProjectOnPlane(moveInputWorld, _wallNormal); + var moveInputWorld = _inputHandler.MoveInputVector; + var moveInWallPlane = Vector3.ProjectOnPlane(moveInputWorld, _wallNormal); - Vector3 wsMove = Vector3.Project(moveInWallPlane, _wallTangentRight); + var wsMove = Vector3.Project(moveInWallPlane, _wallTangentRight); - float ad = inputs.MoveAxisRight; + var ad = inputs.MoveAxisRight; - float sideDot = Vector3.Dot(_wallNormal, _motor.CharacterRight); + var sideDot = Vector3.Dot(_wallNormal, _motor.CharacterRight); if (sideDot < 0) ad = -ad; - Vector3 adMove = _wallTangentUp * (-ad); + var adMove = _wallTangentUp * (-ad); - Vector3 finalMove = wsMove + adMove; + var finalMove = wsMove + adMove; finalMove = finalMove.normalized * moveInputWorld.magnitude; - Vector3 targetVelocity = finalMove * WallRunSpeed; + var targetVelocity = finalMove * _wallRunSpeed; currentVelocity = Vector3.Lerp( currentVelocity, targetVelocity, - 1f - Mathf.Exp(-WallRunAcceleration * deltaTime) + 1f - Mathf.Exp(-_wallRunAcceleration * deltaTime) ); - currentVelocity += Physics.gravity * (WallRunGravityScale * deltaTime); + currentVelocity += Physics.gravity * (_wallRunGravityScale * deltaTime); - float distanceToWall = Vector3.Dot(_motor.TransientPosition - _wallContactPoint, _wallNormal); + var distanceToWall = Vector3.Dot(_motor.TransientPosition - _wallContactPoint, _wallNormal); if (Mathf.Abs(distanceToWall) > 0.8f) { DetachFromWall(false); @@ -160,16 +145,15 @@ namespace Code.Gameplay.Character.Controller.Abilities private bool IsWallStillPresent() { - if (_motor == null) return false; + if (!_motor) return false; - Vector3 characterCenter = _motor.TransientPosition; - Vector3 characterForward = _motor.CharacterForward; - Vector3 characterRight = _motor.CharacterRight; - Vector3 characterUp = _motor.CharacterUp; + var characterCenter = _motor.TransientPosition; + var characterRight = _motor.CharacterRight; + var characterUp = _motor.CharacterUp; - float checkDistance = 0.45f; - Vector3 rayOrigin = characterCenter + characterUp * 0.2f; - Vector3 rayDir = -_wallNormal; + const float checkDistance = 0.45f; + var rayOrigin = characterCenter + characterUp * 0.2f; + var rayDir = -_wallNormal; Vector3[] offsets = { Vector3.zero, @@ -181,83 +165,60 @@ namespace Code.Gameplay.Character.Controller.Abilities foreach (var offset in offsets) { - if (Physics.Raycast(rayOrigin + offset, rayDir, out RaycastHit hit, checkDistance, - _motor.CollidableLayers, QueryTriggerInteraction.Ignore)) - { - float dotWithUp = Mathf.Abs(Vector3.Dot(hit.normal, characterUp)); - if (dotWithUp < _surfaceAngleCos) - { - _wallNormal = hit.normal.normalized; - _wallContactPoint = hit.point; + if (!Physics.Raycast(rayOrigin + offset, rayDir, out var hit, checkDistance, + _motor.CollidableLayers, QueryTriggerInteraction.Ignore)) continue; + + var dotWithUp = Mathf.Abs(Vector3.Dot(hit.normal, characterUp)); + + if (!(dotWithUp < _surfaceAngleCos)) continue; + + _wallNormal = hit.normal.normalized; + _wallContactPoint = hit.point; - /*_wallTangentUp = Vector3.ProjectOnPlane(_motor.CharacterUp, _wallNormal).normalized; - if (_wallTangentUp.sqrMagnitude < 0.01f) _wallTangentUp = Vector3.up; - _wallTangentRight = Vector3.Cross(_wallNormal, _wallTangentUp).normalized; - */ - - return true; - } - } + return true; } return false; } - public void DetachFromWall(bool withImpulse) + private void DetachFromWall(bool withImpulse) { - if (!_isWallRunning) return; + if (!IsWallRunning) return; - _isWallRunning = false; + IsWallRunning = false; - if (withImpulse && _motor != null) - { - Vector3 detachImpulse = -_wallNormal * WallDetachImpulse; - _motor.BaseVelocity += detachImpulse; - } + if (!withImpulse || !_motor) return; + + var detachImpulse = -_wallNormal * _wallDetachImpulse; + _motor.BaseVelocity += detachImpulse; } public Vector3 GetWallNormal() => _wallNormal; - public bool TryGetWallTangents(out Vector3 up, out Vector3 right) - { - if (!_isWallRunning) - { - up = right = Vector3.zero; - return false; - } - up = _wallTangentUp; - right = _wallTangentRight; - return true; - } - public bool CanWallRun() - { - return !_isWallRunning && !_motor.GroundingStatus.IsStableOnGround; - } - public void PerformWallJump(CharacterInputs inputs, Quaternion cameraRotation) { - if (!_isWallRunning || _motor == null) return; + if (!IsWallRunning || !_motor) return; - _isWallRunning = false; + IsWallRunning = false; - Vector3 wallAway = _wallNormal; - Vector3 wallUp = _wallTangentUp; + var wallAway = _wallNormal; + var wallUp = _wallTangentUp; - Vector3 playerForward = cameraRotation * Vector3.forward; + var playerForward = cameraRotation * Vector3.forward; - Vector3 forwardInWallPlane = Vector3.ProjectOnPlane(playerForward, _wallNormal).normalized; + var forwardInWallPlane = Vector3.ProjectOnPlane(playerForward, _wallNormal).normalized; if (forwardInWallPlane.sqrMagnitude < 0.01f) forwardInWallPlane = _wallTangentRight; - Vector3 jumpDirection = + var jumpDirection = forwardInWallPlane * 0.2f + wallAway * 0.4f + wallUp * 0.4f; jumpDirection = jumpDirection.normalized; - float wallJumpForce = WallDetachImpulse * 2f; + var wallJumpForce = _wallDetachImpulse * 2f; - Vector3 jumpImpulse = jumpDirection * wallJumpForce; + var jumpImpulse = jumpDirection * wallJumpForce; _motor.BaseVelocity += jumpImpulse;