diff --git a/Assets/_DDD/_Scripts/RestaurantCharacter/RestaurantPlayerDataSo.cs b/Assets/_DDD/_Scripts/RestaurantCharacter/RestaurantPlayerDataSo.cs index 5aad7b6c3..821f72879 100644 --- a/Assets/_DDD/_Scripts/RestaurantCharacter/RestaurantPlayerDataSo.cs +++ b/Assets/_DDD/_Scripts/RestaurantCharacter/RestaurantPlayerDataSo.cs @@ -6,13 +6,23 @@ namespace DDD [CreateAssetMenu(fileName = "RestaurantPlayerDataSo", menuName = "ScriptableObjects/RestaurantPlayerDataSo")] public class RestaurantPlayerDataSo : ScriptableObject { + public bool IsDrawLineDebug = true; + public bool IsMoveEnabled = true; public float MoveSpeed = 7f; + public float Acceleration = 70f; + public float Deceleration = 350f; public bool IsDashEnabled = true; public float DashSpeed = 20f; public float DashTime = 0.2f; public float DashCooldown = 2f; + + [Tooltip("슬라이딩이 적용되지 않는 충돌체 레이어 (Ground 등)")] + public LayerMask IgnoreSlidingLayerMask; + + [Range(0f, 3f), Tooltip("슬라이딩 보정 제곱\n낮을수록 슬라이딩이 잘 됨")] + public float SlidingThreshold = 0.5f; public string WalkingSfxName; public string DashSfxName; diff --git a/Assets/_DDD/_Scripts/RestaurantCharacter/RestaurantPlayerMovement.cs b/Assets/_DDD/_Scripts/RestaurantCharacter/RestaurantPlayerMovement.cs index 1b93152e0..12cd2ff23 100644 --- a/Assets/_DDD/_Scripts/RestaurantCharacter/RestaurantPlayerMovement.cs +++ b/Assets/_DDD/_Scripts/RestaurantCharacter/RestaurantPlayerMovement.cs @@ -2,17 +2,23 @@ using System.Collections; using UnityEngine; using UnityEngine.InputSystem; +using Vector2 = UnityEngine.Vector2; +using Vector3 = UnityEngine.Vector3; namespace DDD { public class RestaurantPlayerMovement : RestaurantCharacterMovement { private Rigidbody _rigidbody; + private BoxCollider _boxCollider; - private RestaurantPlayerDataSo _playerData; + private RestaurantPlayerDataSo _playerDataSo; + private LineRenderer _inputLineRenderer; + private LineRenderer _velocityLineRenderer; private Vector3 _inputDirection; private Vector3 _currentDirection; + private Vector3 _currentVelocity; private bool _isMoving; private bool _isDashing; private bool _isDashCooldown; @@ -24,17 +30,18 @@ public class RestaurantPlayerMovement : RestaurantCharacterMovement private void Awake() { _rigidbody = GetComponent(); + _boxCollider = GetComponent(); } private async void Start() { try { - _playerData = await AssetManager.LoadAsset(DataConstants.RestaurantPlayerDataSo); + _playerDataSo = await AssetManager.LoadAsset(DataConstants.RestaurantPlayerDataSo); - _playerData.MoveActionReference.action.performed += OnMove; - _playerData.MoveActionReference.action.canceled += OnMove; - _playerData.DashActionReference.action.performed += OnDash; + _playerDataSo.MoveActionReference.action.performed += OnMove; + _playerDataSo.MoveActionReference.action.canceled += OnMove; + _playerDataSo.DashActionReference.action.performed += OnDash; _isInitialized = true; } @@ -52,18 +59,96 @@ private void FixedUpdate() { Move(); } + + if (_playerDataSo.IsDrawLineDebug) + { + DrawLineDebug(); + } } private void OnDestroy() { - if (_playerData) + if (_playerDataSo) { - _playerData.MoveActionReference.action.performed -= OnMove; - _playerData.MoveActionReference.action.canceled -= OnMove; - _playerData.DashActionReference.action.performed -= OnDash; + _playerDataSo.MoveActionReference.action.performed -= OnMove; + _playerDataSo.MoveActionReference.action.canceled -= OnMove; + _playerDataSo.DashActionReference.action.performed -= OnDash; } } + private void DrawLineDebug() + { + Vector3 origin = transform.position; + + if (_inputDirection != Vector3.zero) + { + Vector3 target = origin + _inputDirection.normalized * 1.5f; + if (_inputLineRenderer == null) + { + _inputLineRenderer = CreateOrGetDebugLineRenderer("DebugLine_Input", 10, 0.1f, Color.blue); + } + + UpdateLineRenderer(_inputLineRenderer, origin, target); + _inputLineRenderer.enabled = true; + } + else if (_inputLineRenderer != null) + { + _inputLineRenderer.enabled = false; + } + + float speed = _currentVelocity.magnitude; + if (speed > 0.01f) + { + Vector3 target = origin + _currentVelocity.normalized * (speed * 0.5f); + + if (_velocityLineRenderer == null) + { + _velocityLineRenderer = CreateOrGetDebugLineRenderer("DebugLine_Velocity", 9, 0.2f, Color.red); + } + + UpdateLineRenderer(_velocityLineRenderer, origin, target); + _velocityLineRenderer.enabled = true; + } + else if (_velocityLineRenderer != null) + { + _velocityLineRenderer.enabled = false; + } + } + + private LineRenderer CreateOrGetDebugLineRenderer(string name, int sortingIndex, float width, Color color) + { + Transform existing = transform.Find(name); + if (existing != null) + { + var lr = existing.GetComponent(); + if (lr != null) + { + lr.startColor = lr.endColor = color; + return lr; + } + } + + var newGameObject = new GameObject(name); + newGameObject.transform.SetParent(transform); + newGameObject.transform.localPosition = Vector3.zero; + + var lineRenderer = newGameObject.AddComponent(); + lineRenderer.positionCount = 2; + lineRenderer.material = new Material(Shader.Find("Sprites/Default")); // URP 호환 + lineRenderer.sortingOrder = sortingIndex; + lineRenderer.startWidth = lineRenderer.endWidth = width; + lineRenderer.startColor = lineRenderer.endColor = color; + lineRenderer.useWorldSpace = true; + + return lineRenderer; + } + + private void UpdateLineRenderer(LineRenderer lr, Vector3 start, Vector3 end) + { + lr.SetPosition(0, start); + lr.SetPosition(1, end); + } + public void SetCurrentDirection(Vector3 normalDirection) { if (_inputDirection == Vector3.zero) return; @@ -79,7 +164,7 @@ private void OnMove(InputAction.CallbackContext context) private bool CanMove() { - return _playerData.IsMoveEnabled && _isDashing == false; + return _playerDataSo.IsMoveEnabled && _isDashing == false; } private void Move() @@ -88,9 +173,44 @@ private void Move() _isMoving = _inputDirection != Vector3.zero; OnMoving?.Invoke(_isMoving); + + if (_isMoving) + { + Vector3 slideDirection = GetSlideAdjustedDirection(_inputDirection.normalized); + Vector3 targetVelocity = slideDirection * _playerDataSo.MoveSpeed; + _currentVelocity = Vector3.MoveTowards(_currentVelocity, targetVelocity, _playerDataSo.Acceleration * Time.fixedDeltaTime); + } + else + { + _currentVelocity = Vector3.MoveTowards(_currentVelocity, Vector3.zero, _playerDataSo.Deceleration * Time.fixedDeltaTime); + } - Vector3 finalVelocity = _inputDirection * _playerData.MoveSpeed; - _rigidbody.linearVelocity = finalVelocity; + _rigidbody.linearVelocity = _currentVelocity; + } + + private Vector3 GetSlideAdjustedDirection(Vector3 inputDirection) + { + Vector3 origin = _boxCollider.bounds.center; + Vector3 halfExtents = _boxCollider.bounds.extents; + Quaternion rotation = transform.rotation; + float distance = _boxCollider.bounds.size.x <= _boxCollider.bounds.size.z + ? _boxCollider.bounds.size.x + : _boxCollider.bounds.size.z; + int layerMask = ~_playerDataSo.IgnoreSlidingLayerMask; + + if (Physics.BoxCast(origin, halfExtents * 0.95f, inputDirection, out RaycastHit hit, rotation, distance, layerMask)) + { + Vector3 slide = Vector3.ProjectOnPlane(inputDirection, hit.normal).normalized; + + float dot = Vector3.Dot(inputDirection.normalized, hit.normal); + float slideFactor = Mathf.Pow(1f - Mathf.Abs(dot), _playerDataSo.SlidingThreshold); + + if (slideFactor < 0.05f) return Vector3.zero; + + return slide * slideFactor; + } + + return inputDirection; } private void OnDash(InputAction.CallbackContext context) @@ -103,7 +223,7 @@ private void OnDash(InputAction.CallbackContext context) private bool CanDash() { - return _playerData.IsDashEnabled && _isDashing == false && _isDashCooldown == false; + return _playerDataSo.IsDashEnabled && _isDashing == false && _isDashCooldown == false; } private IEnumerator DashCoroutine() @@ -111,16 +231,19 @@ private IEnumerator DashCoroutine() _isDashing = true; _isDashCooldown = true; - OnDashing?.Invoke(_playerData.DashTime); + OnDashing?.Invoke(_playerDataSo.DashTime); - Vector3 dashVelocity = _currentDirection.normalized * _playerData.DashSpeed; + Vector3 currentDirection = _currentDirection.normalized; + Vector3 slideDashDirection = GetSlideAdjustedDirection(currentDirection); + + Vector3 dashVelocity = slideDashDirection * _playerDataSo.DashSpeed; _rigidbody.linearVelocity = dashVelocity; - yield return new WaitForSeconds(_playerData.DashTime); + yield return new WaitForSeconds(_playerDataSo.DashTime); _isDashing = false; - yield return new WaitForSeconds(_playerData.DashCooldown); + yield return new WaitForSeconds(_playerDataSo.DashCooldown); _isDashCooldown = false; }