From ef384bf59c86ead2872f8876e89d02445fbe1f11 Mon Sep 17 00:00:00 2001 From: Jeonghyeon Ha Date: Tue, 15 Jul 2025 20:10:46 +0900 Subject: [PATCH] =?UTF-8?q?DDD-43=20=EC=BD=94=EB=93=9C=20=EB=A6=AC?= =?UTF-8?q?=ED=8C=A9=ED=86=A0=EB=A7=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Assets/0_Voyage/Ship/Player/PlayerShip.prefab | 61 +++- .../_Scripts/Ship/VoyagePlayerShipMovement.cs | 226 +++++++------ .../Ship/VoyagePlayerShipMovementDebug.cs | 296 ++++++++++-------- 3 files changed, 342 insertions(+), 241 deletions(-) diff --git a/Assets/0_Voyage/Ship/Player/PlayerShip.prefab b/Assets/0_Voyage/Ship/Player/PlayerShip.prefab index e104f8cec..86f046578 100644 --- a/Assets/0_Voyage/Ship/Player/PlayerShip.prefab +++ b/Assets/0_Voyage/Ship/Player/PlayerShip.prefab @@ -14,6 +14,7 @@ GameObject: - component: {fileID: -1082383067592254908} - component: {fileID: 7722456790212551628} - component: {fileID: 3140672700990605547} + - component: {fileID: 66612183539046142} m_Layer: 0 m_Name: PlayerShip m_TagString: Untagged @@ -107,15 +108,17 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: 2607481b15fd548b18ca4897db56ab3f, type: 3} m_Name: m_EditorClassIdentifier: - maxSpeed: 20 - accelerationRate: 1 - dragFactor: 0.98 - minSpeedThreshold: 0.1 - rotationSpeed: 270 - minRotationSpeed: 90 - rotationAccelerationRate: 5 - turnSpeedPenalty: 0.5 - maxTurnAngle: 180 + movementSettings: + maxSpeed: 20 + accelerationRate: 1 + dragFactor: 0.98 + minSpeedThreshold: 0.1 + rotationSettings: + maxRotationSpeed: 270 + minRotationSpeed: 90 + accelerationRate: 5 + turnSpeedPenalty: 0.5 + maxTurnAngle: 180 --- !u!114 &7722456790212551628 MonoBehaviour: m_ObjectHideFlags: 0 @@ -157,9 +160,43 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: 3d5c5f51b32b4633b887d096554c6cd9, type: 3} m_Name: m_EditorClassIdentifier: - showDebugVisuals: 1 - debugLineLength: 5 - debugLineWidth: 0.1 + settings: + showDebugVisuals: 1 + lineLength: 5 + lineWidth: 0.1 + speedLineColor: {r: 0, g: 1, b: 0, a: 1} + rotationSpeedLineColor: {r: 1, g: 0, b: 1, a: 1} + rotationDeltaLineColor: {r: 1, g: 0.92156863, b: 0.015686275, a: 1} + tiltLineColor: {r: 1, g: 0, b: 0, a: 1} + waveHeightLineColor: {r: 0, g: 0, b: 1, a: 1} + wavePatternLineColor: {r: 0, g: 1, b: 1, a: 1} +--- !u!54 &66612183539046142 +Rigidbody: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1553910019582315619} + serializedVersion: 4 + m_Mass: 1 + m_Drag: 0 + m_AngularDrag: 0.05 + m_CenterOfMass: {x: 0, y: 0, z: 0} + m_InertiaTensor: {x: 1, y: 1, z: 1} + m_InertiaRotation: {x: 0, y: 0, z: 0, w: 1} + m_IncludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_ExcludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_ImplicitCom: 1 + m_ImplicitTensor: 1 + m_UseGravity: 0 + m_IsKinematic: 0 + m_Interpolate: 0 + m_Constraints: 0 + m_CollisionDetection: 0 --- !u!1 &6407855916708530114 GameObject: m_ObjectHideFlags: 0 diff --git a/Assets/0_Voyage/_Scripts/Ship/VoyagePlayerShipMovement.cs b/Assets/0_Voyage/_Scripts/Ship/VoyagePlayerShipMovement.cs index 3096a1231..a745566a9 100644 --- a/Assets/0_Voyage/_Scripts/Ship/VoyagePlayerShipMovement.cs +++ b/Assets/0_Voyage/_Scripts/Ship/VoyagePlayerShipMovement.cs @@ -2,178 +2,208 @@ using UnityEngine; using UnityEngine.InputSystem; /// -/// 플레이어 배의 움직임을 제어하는 컴포넌트 -/// 속도, 회전, 틸트, 파도 효과 등을 관리합니다. +/// 플레이어 배의 기본 이동과 회전을 처리하는 컴포넌트 /// +[RequireComponent(typeof(Rigidbody))] public class VoyagePlayerShipMovement : MonoBehaviour { + #region Settings + [System.Serializable] + public class MovementSettings + { + [Tooltip("배의 최대 이동 속도")] + public float maxSpeed = 20f; + public float accelerationRate = 1f; + public float dragFactor = 0.98f; + public float minSpeedThreshold = 0.1f; + } + + [System.Serializable] + public class RotationSettings + { + public float maxRotationSpeed = 270f; + public float minRotationSpeed = 90f; + public float accelerationRate = 5f; + [Tooltip("선회 시 감속 정도 (0: 감속 없음, 1: 완전 정지)")] + public float turnSpeedPenalty = 0.5f; + [Tooltip("최대 감속이 적용되는 각도")] + public float maxTurnAngle = 180f; + } + #endregion + #region Inspector Fields - - [Header("기본 이동 설정")] - [Tooltip("배의 최대 이동 속도")] - [SerializeField] private float maxSpeed = 20f; - [SerializeField] private float accelerationRate = 1f; - [SerializeField] private float dragFactor = 0.98f; - [SerializeField] private float minSpeedThreshold = 0.1f; - - [Header("회전 설정")] - [SerializeField] private float rotationSpeed = 270f; - [SerializeField] private float minRotationSpeed = 90f; - [SerializeField] private float rotationAccelerationRate = 5f; - [SerializeField] private float turnSpeedPenalty = 0.5f; - [SerializeField] private float maxTurnAngle = 180f; + [SerializeField] + private MovementSettings movementSettings = new(); + [SerializeField] + private RotationSettings rotationSettings = new(); + #endregion + + #region Properties + public Vector2 CurrentInput => currentInput; + public float CurrentRotationSpeed => currentRotationSpeed; + public float CurrentSpeed => currentSpeed; + public float MaxSpeed => movementSettings.maxSpeed; + public Vector3 CurrentVelocity => currentVelocity; #endregion #region Private Fields - private Vector3 currentVelocity; private Vector2 currentInput; - public Vector2 CurrentInput => currentInput; private float currentRotationSpeed; - public float CurrentRotationSpeed => currentRotationSpeed; private float targetSpeed; private float currentSpeed; - public float CurrentSpeed => currentSpeed; - public float MaxSpeed => maxSpeed; - - // 회전 틸트 관련 - private float currentRotationTilt; - private float lastRotationY; - private float currentAngularVelocity; - - // 가속 틸트 관련 - private float currentAccelTilt; - private float accelTiltVelocity; - private float prevSpeed; - - // 파도 효과 관련 - private float waveTime; - private float waveRandomOffset; - private float currentWaveHeight; - #endregion #region Unity Messages private void FixedUpdate() { - UpdateMovement(); + UpdateShipMovement(); + } + #endregion + + #region Public Methods + public void OnMove(InputAction.CallbackContext context) + { + currentInput = context.ReadValue(); } #endregion #region Movement Methods - private void UpdateMovement() + private void UpdateShipMovement() { if (IsMoving()) { - HandleMovement(); - HandleRotation(); + UpdateMovementWithInput(); } else { - DecelerateMovement(); + DecelerateShip(); } - ApplyDrag(); - ApplyMovement(); + ApplyDragForce(); + ApplyFinalMovement(); } - private bool IsMoving() + private void UpdateMovementWithInput() { - return currentInput.magnitude > minSpeedThreshold; + UpdateSpeed(); + UpdateRotation(); } - private void HandleMovement() + private void UpdateSpeed() { float baseTargetSpeed = CalculateBaseTargetSpeed(); float turnPenaltyFactor = CalculateTurnPenaltyFactor(); targetSpeed = baseTargetSpeed * turnPenaltyFactor; - currentSpeed = Mathf.Lerp(currentSpeed, targetSpeed, accelerationRate * Time.fixedDeltaTime); + currentSpeed = Mathf.Lerp(currentSpeed, targetSpeed, + movementSettings.accelerationRate * Time.fixedDeltaTime); if (ShouldStop()) { - currentSpeed = 0f; + StopShip(); } UpdateVelocityVector(); } - private void HandleRotation() + private void UpdateRotation() { - if (IsMoving()) - { - Vector3 inputDirection = new Vector3(currentInput.x, 0, currentInput.y).normalized; - Quaternion targetRotation = Quaternion.LookRotation(inputDirection, Vector3.up); + if (!IsMoving()) return; - // 회전 속도를 현재 속도에 비례하도록 설정 - float desiredRotationSpeed = rotationSpeed * (currentSpeed / maxSpeed); - desiredRotationSpeed = Mathf.Max(desiredRotationSpeed, minRotationSpeed); - currentRotationSpeed = Mathf.Lerp(currentRotationSpeed, desiredRotationSpeed, - rotationAccelerationRate * Time.fixedDeltaTime); - - // 기본 회전 적용 (오브젝트 전체) - transform.rotation = Quaternion.RotateTowards( - transform.rotation, - targetRotation, - currentRotationSpeed * Time.fixedDeltaTime - ); - } + Quaternion targetRotation = CalculateTargetRotation(); + float rotationSpeed = CalculateRotationSpeed(); + + ApplyRotation(targetRotation, rotationSpeed); } - + #endregion + + #region Helper Methods + private bool IsMoving() + { + return currentInput.magnitude > movementSettings.minSpeedThreshold; + } + private float CalculateBaseTargetSpeed() { - return Mathf.Clamp01(currentInput.magnitude) * maxSpeed; + return Mathf.Clamp01(currentInput.magnitude) * movementSettings.maxSpeed; } private float CalculateTurnPenaltyFactor() { Vector3 inputDirection = new Vector3(currentInput.x, 0, currentInput.y).normalized; float angleDifference = Vector3.Angle(transform.forward, inputDirection); - return Mathf.Clamp01(1f - (angleDifference / maxTurnAngle * turnSpeedPenalty)); + float penaltyFactor = angleDifference / rotationSettings.maxTurnAngle * rotationSettings.turnSpeedPenalty; + + return Mathf.Clamp01(1f - penaltyFactor); + } + + private Quaternion CalculateTargetRotation() + { + Vector3 inputDirection = new Vector3(currentInput.x, 0, currentInput.y).normalized; + return Quaternion.LookRotation(inputDirection, Vector3.up); + } + + private float CalculateRotationSpeed() + { + float speedBasedRotation = rotationSettings.maxRotationSpeed * (currentSpeed / movementSettings.maxSpeed); + float desiredRotationSpeed = Mathf.Max(speedBasedRotation, rotationSettings.minRotationSpeed); + + return Mathf.Lerp(currentRotationSpeed, desiredRotationSpeed, + rotationSettings.accelerationRate * Time.fixedDeltaTime); + } + + private void ApplyRotation(Quaternion targetRotation, float rotationSpeed) + { + currentRotationSpeed = rotationSpeed; + transform.rotation = Quaternion.RotateTowards( + transform.rotation, + targetRotation, + rotationSpeed * Time.fixedDeltaTime + ); } private bool ShouldStop() { - return currentSpeed < minSpeedThreshold && targetSpeed < minSpeedThreshold; + return currentSpeed < movementSettings.minSpeedThreshold && + targetSpeed < movementSettings.minSpeedThreshold; + } + + private void StopShip() + { + currentSpeed = 0f; + currentVelocity = Vector3.zero; } private void UpdateVelocityVector() { currentVelocity = transform.forward * currentSpeed; } - #endregion - - private void ApplyDrag() + + private void DecelerateShip() { - currentSpeed *= dragFactor; - - // 최소 속도 이하면 완전히 정지 - if (currentSpeed < minSpeedThreshold) - { - currentSpeed = 0f; - } - - // 현재 방향으로 감속된 속도 적용 - currentVelocity = transform.forward * currentSpeed; + currentSpeed = Mathf.Lerp(currentSpeed, 0f, + movementSettings.accelerationRate * Time.fixedDeltaTime); + currentRotationSpeed = 0f; } - private void ApplyMovement() + private void ApplyDragForce() + { + currentSpeed *= movementSettings.dragFactor; + if (currentSpeed < movementSettings.minSpeedThreshold) + { + StopShip(); + } + else + { + UpdateVelocityVector(); + } + } + + private void ApplyFinalMovement() { transform.position += currentVelocity * Time.fixedDeltaTime; } - - private void DecelerateMovement() - { - // 입력이 없을 때는 서서히 감속 - currentSpeed = Mathf.Lerp(currentSpeed, 0f, accelerationRate * Time.fixedDeltaTime); - currentRotationSpeed = 0; - } - - #region Input Handling - public void OnMove(InputAction.CallbackContext context) - { - currentInput = context.ReadValue(); - } #endregion } \ No newline at end of file diff --git a/Assets/0_Voyage/_Scripts/Ship/VoyagePlayerShipMovementDebug.cs b/Assets/0_Voyage/_Scripts/Ship/VoyagePlayerShipMovementDebug.cs index 58d3e2ceb..caaca336a 100644 --- a/Assets/0_Voyage/_Scripts/Ship/VoyagePlayerShipMovementDebug.cs +++ b/Assets/0_Voyage/_Scripts/Ship/VoyagePlayerShipMovementDebug.cs @@ -3,176 +3,180 @@ using UnityEngine; namespace Voyage { #if UNITY_EDITOR - using UnityEngine; - - [RequireComponent(typeof(VoyagePlayerShipMovement)), RequireComponent(typeof(VoyagePlayerShipMovementVisual))] + /// + /// 배의 움직임을 시각적으로 디버깅하기 위한 컴포넌트 + /// + [RequireComponent(typeof(VoyagePlayerShipMovement))] + [RequireComponent(typeof(VoyagePlayerShipMovementVisual))] public class VoyagePlayerShipDebug : MonoBehaviour { - [Header("Debug Visualization")] - [SerializeField] private bool showDebugVisuals = true; - [SerializeField] private float debugLineLength = 5f; - [SerializeField] private float debugLineWidth = 0.1f; + #region Debug Settings + [System.Serializable] + public class DebugSettings + { + public bool showDebugVisuals = true; + public float lineLength = 5f; + public float lineWidth = 0.1f; + + [Header("라인 색상")] + public Color speedLineColor = Color.green; + public Color rotationSpeedLineColor = Color.magenta; + public Color rotationDeltaLineColor = Color.yellow; + public Color tiltLineColor = Color.red; + public Color waveHeightLineColor = Color.blue; + public Color wavePatternLineColor = Color.cyan; + } - private LineRenderer _speedLineRenderer; - private LineRenderer _rotationSpeedLineRenderer; - private LineRenderer _rotationDeltaLineRenderer; - private LineRenderer _TiltLineRenderer; - private LineRenderer _waveHeightLineRenderer; - private LineRenderer _wavePatternLineRenderer; + [SerializeField] private DebugSettings settings = new(); + #endregion + #region Line Renderers + private class DebugLines + { + public LineRenderer Speed { get; set; } + public LineRenderer RotationSpeed { get; set; } + public LineRenderer RotationDelta { get; set; } + public LineRenderer Tilt { get; set; } + public LineRenderer WaveHeight { get; set; } + public LineRenderer WavePattern { get; set; } + } + + private DebugLines lines = new(); + #endregion + + #region Components private VoyagePlayerShipMovement movement; private VoyagePlayerShipMovementVisual movementVisual; + #endregion - + #region Unity Messages private void Start() { - if (!showDebugVisuals) return; + if (!settings.showDebugVisuals) return; - movement = GetComponent(); - movementVisual = GetComponent(); - - InitializeDebugVisuals(); + InitializeComponents(); + InitializeDebugLines(); } private void Update() { - if (!showDebugVisuals) return; - UpdateDebugVisuals(); + if (!settings.showDebugVisuals) return; + UpdateAllDebugLines(); + } + #endregion + + #region Initialization + private void InitializeComponents() + { + movement = GetComponent(); + movementVisual = GetComponent(); } - private void InitializeDebugVisuals() + private void InitializeDebugLines() { - if (!showDebugVisuals) return; - - // 속도 표시 - _speedLineRenderer = CreateLineRenderer("SpeedLine", Color.green); - // 회전 방향 표시 - _rotationSpeedLineRenderer = CreateLineRenderer("RotationSpeedLine", Color.magenta); - // 회전 방향 표시 - _rotationDeltaLineRenderer = CreateLineRenderer("RotationDeltaLine", Color.yellow); - // 틸트 표시 - _TiltLineRenderer = CreateLineRenderer("TiltLine", Color.red); - // 파도 높이 표시 - _waveHeightLineRenderer = CreateLineRenderer("WaveHeightLine", Color.blue); - // 파도 패턴 표시 - _wavePatternLineRenderer = CreateLineRenderer("WavePatternLine", Color.cyan); - _wavePatternLineRenderer.positionCount = 50; // 파도 패턴을 위한 더 많은 점 + lines.Speed = CreateLineRenderer("SpeedLine", settings.speedLineColor); + lines.RotationSpeed = CreateLineRenderer("RotationSpeedLine", settings.rotationSpeedLineColor); + lines.RotationDelta = CreateLineRenderer("RotationDeltaLine", settings.rotationDeltaLineColor); + lines.Tilt = CreateLineRenderer("TiltLine", settings.tiltLineColor); + lines.WaveHeight = CreateLineRenderer("WaveHeightLine", settings.waveHeightLineColor); + lines.WavePattern = CreateLineRenderer("WavePatternLine", settings.wavePatternLineColor, 50); } + #endregion - private void UpdateDebugVisuals() + #region Line Updates + private void UpdateAllDebugLines() { - if (!showDebugVisuals) return; - - // 속도 벡터 표시 UpdateSpeedLine(); - - // 회전 방향 및 각속도 표시 - UpdateRotationSpeedLine(); - UpdateRotationDeltaLine(); - // 회전 틸트 표시 + UpdateRotationLines(); UpdateTiltLine(); - // 파도 높이와 패턴 표시 UpdateWaveVisualization(); } - - private float GetCurrentSpeed() => movement.CurrentSpeed; - private float GetMaxSpeed() => movement.MaxSpeed; - private float GetRotationSpeed() => movement.CurrentRotationSpeed; - private Vector2 GetCurrentInput() => movement.CurrentInput; private void UpdateSpeedLine() { - Vector3 start = transform.position + Vector3.up * 1.5f; - Vector3 end = start + transform.forward * ((GetCurrentSpeed() / GetMaxSpeed()) * debugLineLength * 2); - DrawLine(_speedLineRenderer, start, end); + Vector3 start = GetDebugLineStart(1.5f); + Vector3 direction = transform.forward * (movement.CurrentSpeed / movement.MaxSpeed); + Vector3 end = start + direction * (settings.lineLength * 2f); + + DrawLine(lines.Speed, start, end); } - private void UpdateRotationSpeedLine() + private void UpdateRotationLines() { - Vector3 start = transform.position + Vector3.up * 1.2f; - // 각속도를 호로 표현 - if (Mathf.Abs(GetRotationSpeed()) > 0.1f) - { - Vector3[] arcPoints = new Vector3[10]; - float radius = debugLineLength * 1f; - float angleStep = GetRotationSpeed() * 1f / (arcPoints.Length - 1); - - for (int i = 0; i < arcPoints.Length; i++) - { - float angle = angleStep * i; - Vector3 point = start + Quaternion.Euler(0, angle, 0) * transform.forward * radius; - arcPoints[i] = point; - } - - _rotationSpeedLineRenderer.positionCount = arcPoints.Length; - _rotationSpeedLineRenderer.SetPositions(arcPoints); - } - else - { - _rotationSpeedLineRenderer.positionCount = 0; - } + UpdateRotationSpeedArc(); + UpdateRotationDeltaArc(); } - private void UpdateRotationDeltaLine() + private void UpdateRotationSpeedArc() { - float deltaAngle = 0f; - if (GetCurrentInput().magnitude > 0.1f) + if (Mathf.Abs(movement.CurrentRotationSpeed) <= 0.1f) { - Vector3 inputDirection = new Vector3(GetCurrentInput().x, 0, GetCurrentInput().y).normalized; - Quaternion targetRotation = Quaternion.LookRotation(inputDirection, Vector3.up); - deltaAngle = Quaternion.Angle(transform.rotation, targetRotation); + lines.RotationSpeed.positionCount = 0; + return; } - Vector3 start = transform.position + Vector3.up * 1.2f; - // 각속도를 호로 표현 - if (Mathf.Abs(deltaAngle) > 0.1f) - { - Vector3[] arcPoints = new Vector3[10]; - float radius = debugLineLength * 1.05f; - float angleStep = deltaAngle * 1f / (arcPoints.Length - 1); + DrawArc(lines.RotationSpeed, + GetDebugLineStart(1.2f), + settings.lineLength, + movement.CurrentRotationSpeed); + } - for (int i = 0; i < arcPoints.Length; i++) - { - float angle = angleStep * i; - Vector3 point = start + Quaternion.Euler(0, angle, 0) * transform.forward * radius; - arcPoints[i] = point; - } - - _rotationDeltaLineRenderer.positionCount = arcPoints.Length; - _rotationDeltaLineRenderer.SetPositions(arcPoints); - } - else + private void UpdateRotationDeltaArc() + { + if (movement.CurrentInput.magnitude <= 0.1f) { - _rotationDeltaLineRenderer.positionCount = 0; + lines.RotationDelta.positionCount = 0; + return; } + + float deltaAngle = CalculateRotationDeltaAngle(); + if (Mathf.Abs(deltaAngle) <= 0.1f) + { + lines.RotationDelta.positionCount = 0; + return; + } + + DrawArc(lines.RotationDelta, + GetDebugLineStart(1.2f), + settings.lineLength * 1.05f, + deltaAngle); } private void UpdateTiltLine() { - Vector3 start = transform.position + Vector3.up * 1.5f; + Vector3 start = GetDebugLineStart(1.5f); Vector3 tiltDirection = movementVisual.MeshTransform.up; - DrawLine(_TiltLineRenderer, start, start + tiltDirection * (debugLineLength * 0.4f)); + DrawLine(lines.Tilt, start, start + tiltDirection * (settings.lineLength * 0.4f)); } private void UpdateWaveVisualization() + { + UpdateWaveHeightLine(); + UpdateWavePatternLine(); + } + + private void UpdateWaveHeightLine() { // 현재 파도 높이 표시 Vector3 waveStart = transform.position + Vector3.up * 1.5f - transform.forward * 1.5f; - Vector3 waveEnd = waveStart + Vector3.up * (GetCurrentWaveHeight() * debugLineLength); - DrawLine(_waveHeightLineRenderer, waveStart, waveEnd); + Vector3 waveEnd = waveStart + Vector3.up * (movementVisual.CurrentWaveHeight * settings.lineLength); + DrawLine(lines.WaveHeight, waveStart, waveEnd); + } + private void UpdateWavePatternLine() + { // 파도 패턴 시각화 - Vector3[] wavePoints = new Vector3[_wavePatternLineRenderer.positionCount]; - float waveLength = debugLineLength * 2f; + Vector3[] wavePoints = new Vector3[lines.WavePattern.positionCount]; + float waveLength = settings.lineLength * 2f; for (int i = 0; i < wavePoints.Length; i++) { - float t = (float)i / (_wavePatternLineRenderer.positionCount - 1); + float t = (float)i / (lines.WavePattern.positionCount - 1); float x = t * waveLength - waveLength * 0.5f; - float currentSpeedByUnit = GetCurrentSpeed() / GetWaveUnitSpeed(); + float currentSpeedByUnit = movement.CurrentSpeed / movementVisual.WaveUnitSpeed; currentSpeedByUnit = Mathf.Clamp01(currentSpeedByUnit); - float waveHeight = Mathf.Lerp(GetMinSpeedWaveHeight(), GetMaxSpeedWaveHeight(), currentSpeedByUnit); - float y = Mathf.Sin((GetWaveTime() + x) * GetBaseWaveFrequency()) * waveHeight; + float waveHeight = Mathf.Lerp(movementVisual.MinSpeedWaveHeight, movementVisual.MaxSpeedWaveHeight, currentSpeedByUnit); + float y = Mathf.Sin((movementVisual.WaveTime + x) * movementVisual.BaseWaveFrequency) * waveHeight; wavePoints[i] = transform.position + Vector3.right * x + @@ -180,43 +184,73 @@ namespace Voyage wavePoints[i] += Vector3.back * 3f + Vector3.down * 1f; } - _wavePatternLineRenderer.SetPositions(wavePoints); + lines.WavePattern.SetPositions(wavePoints); + } + #endregion + + #region Helper Methods + private Vector3 GetDebugLineStart(float heightOffset) + { + return transform.position + Vector3.up * heightOffset; } - private float GetCurrentWaveHeight() => movementVisual.CurrentWaveHeight; - private float GetWaveUnitSpeed() => movementVisual.WaveUnitSpeed; - private float GetMinSpeedWaveHeight() => movementVisual.MinSpeedWaveHeight; - private float GetMaxSpeedWaveHeight() => movementVisual.MaxSpeedWaveHeight; - private float GetWaveTime() => movementVisual.WaveTime; - private float GetBaseWaveFrequency() => movementVisual.BaseWaveFrequency; - - private LineRenderer CreateLineRenderer(string name, Color color) + private float CalculateRotationDeltaAngle() { - GameObject lineObj = new GameObject(name); + Vector3 inputDirection = new Vector3(movement.CurrentInput.x, 0, movement.CurrentInput.y).normalized; + Quaternion targetRotation = Quaternion.LookRotation(inputDirection, Vector3.up); + return Quaternion.Angle(transform.rotation, targetRotation); + } + + private void DrawArc(LineRenderer lineRenderer, Vector3 center, float radius, float totalAngle) + { + const int ArcSegments = 10; + Vector3[] arcPoints = new Vector3[ArcSegments]; + float angleStep = totalAngle / (ArcSegments - 1); + + for (int i = 0; i < ArcSegments; i++) + { + float angle = angleStep * i; + Vector3 point = center + Quaternion.Euler(0, angle, 0) * transform.forward * radius; + arcPoints[i] = point; + } + + lineRenderer.positionCount = ArcSegments; + lineRenderer.SetPositions(arcPoints); + } + + private LineRenderer CreateLineRenderer(string name, Color color, int pointCount = 2) + { + GameObject lineObj = new GameObject($"Debug_{name}"); lineObj.transform.SetParent(transform); + LineRenderer line = lineObj.AddComponent(); + InitializeLineRenderer(line, color, pointCount); + + return line; + } - line.startWidth = debugLineWidth; - line.endWidth = debugLineWidth; + private void InitializeLineRenderer(LineRenderer line, Color color, int pointCount) + { + line.startWidth = settings.lineWidth; + line.endWidth = settings.lineWidth; line.material = new Material(Shader.Find("Universal Render Pipeline/Unlit")); - line.startColor = color; - line.endColor = color; - line.positionCount = 2; - + line.startColor = line.endColor = color; + line.positionCount = pointCount; + line.shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.Off; line.receiveShadows = false; line.material.color = color; - - return line; } private void DrawLine(LineRenderer line, Vector3 start, Vector3 end) { if (line is null) return; + line.positionCount = 2; line.SetPosition(0, start); line.SetPosition(1, end); } + #endregion } #endif } \ No newline at end of file