diff --git a/Assets/01.Scenes/77.SailTest_Ship.unity b/Assets/01.Scenes/77.SailTest_Ship.unity index e741d3385..7f05941bb 100644 --- a/Assets/01.Scenes/77.SailTest_Ship.unity +++ b/Assets/01.Scenes/77.SailTest_Ship.unity @@ -90187,8 +90187,8 @@ Transform: m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 943285313} serializedVersion: 2 - m_LocalRotation: {x: 0.22409342, y: 0, z: 0, w: 0.97456765} - m_LocalPosition: {x: 0, y: 8.74, z: -18} + m_LocalRotation: {x: 0.25884834, y: 0, z: 0, w: 0.965918} + m_LocalPosition: {x: 0, y: 11.014116, z: -19.074339} m_LocalScale: {x: 1, y: 1, z: 1} m_ConstrainProportionsScale: 0 m_Children: [] @@ -141074,7 +141074,7 @@ Transform: m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1413354196} serializedVersion: 2 - m_LocalRotation: {x: -0, y: 0.7816503, z: -0, w: 0.62371695} + m_LocalRotation: {x: -0, y: 0.4456134, z: -0, w: 0.8952256} m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} m_ConstrainProportionsScale: 0 @@ -152373,8 +152373,8 @@ GameObject: m_Component: - component: {fileID: 1498712852} - component: {fileID: 1498712855} - - component: {fileID: 1498712854} - - component: {fileID: 1498712856} + - component: {fileID: 1498712857} + - component: {fileID: 1498712858} m_Layer: 9 m_Name: CinemachineCamera_Back m_TagString: Untagged @@ -152390,32 +152390,13 @@ Transform: m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1498712851} serializedVersion: 2 - m_LocalRotation: {x: 0.22409342, y: 0, z: 0, w: 0.97456765} - m_LocalPosition: {x: 0, y: 8.74, z: -18} + m_LocalRotation: {x: 0.25884834, y: 0, z: 0, w: 0.965918} + m_LocalPosition: {x: 0, y: 11.014116, z: -19.074339} m_LocalScale: {x: 1, y: 1, z: 1} m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 1885259736} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!114 &1498712854 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1498712851} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: b617507da6d07e749b7efdb34e1173e1, type: 3} - m_Name: - m_EditorClassIdentifier: - TrackerSettings: - BindingMode: 4 - PositionDamping: {x: 1, y: 1, z: 0} - AngularDampingMode: 0 - RotationDamping: {x: 1, y: 1, z: 1} - QuaternionDamping: 1 - FollowOffset: {x: 0, y: 8.74, z: -18} --- !u!114 &1498712855 MonoBehaviour: m_ObjectHideFlags: 0 @@ -152459,7 +152440,70 @@ MonoBehaviour: BarrelClipping: 0.25 Anamorphism: 0 BlendHint: 0 ---- !u!114 &1498712856 +--- !u!114 &1498712857 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1498712851} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 3b5d7c088409d9a40b7b09aa707777f8, type: 3} + m_Name: + m_EditorClassIdentifier: + TargetOffset: {x: 0, y: 5, z: 0} + TrackerSettings: + BindingMode: 4 + PositionDamping: {x: 1, y: 1, z: 1} + AngularDampingMode: 0 + RotationDamping: {x: 1, y: 1, z: 1} + QuaternionDamping: 1 + OrbitStyle: 0 + Radius: 20 + Orbits: + Top: + Radius: 2 + Height: 5 + Center: + Radius: 4 + Height: 2.25 + Bottom: + Radius: 2.5 + Height: 0.1 + SplineCurvature: 0.5 + RecenteringTarget: 2 + HorizontalAxis: + Value: 0 + Center: 0 + Range: {x: -180, y: 180} + Wrap: 1 + Recentering: + Enabled: 0 + Wait: 1 + Time: 2 + Restrictions: 0 + VerticalAxis: + Value: 17.5 + Center: 17.5 + Range: {x: -10, y: 45} + Wrap: 0 + Recentering: + Enabled: 0 + Wait: 1 + Time: 2 + Restrictions: 0 + RadialAxis: + Value: 1 + Center: 1 + Range: {x: 1, y: 1} + Wrap: 0 + Recentering: + Enabled: 0 + Wait: 1 + Time: 2 + Restrictions: 0 +--- !u!114 &1498712858 MonoBehaviour: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} @@ -154945,7 +154989,7 @@ Transform: m_GameObject: {fileID: 1528083691} serializedVersion: 2 m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} - m_LocalPosition: {x: 0, y: 8.74, z: -18} + m_LocalPosition: {x: 0, y: 20, z: -20} m_LocalScale: {x: 1, y: 1, z: 1} m_ConstrainProportionsScale: 0 m_Children: diff --git a/Assets/0_Voyage/Ship/Player/PlayerShip.prefab b/Assets/0_Voyage/Ship/Player/PlayerShip.prefab index 56a377e75..69715f9e6 100644 --- a/Assets/0_Voyage/Ship/Player/PlayerShip.prefab +++ b/Assets/0_Voyage/Ship/Player/PlayerShip.prefab @@ -107,14 +107,13 @@ MonoBehaviour: m_EditorClassIdentifier: maxSpeed: 20 rotationSpeed: 180 + minRotationSpeed: 60 + rotationAccelerationRate: 5 accelerationRate: 1 minSpeedThreshold: 0.1 dragFactor: 0.98 turnSpeedPenalty: 0.5 maxTurnAngle: 180 - showDebugLines: 1 - debugLineLength: 5 - debugLineHeightStep: 0.02 maxRotationTiltAngle: 15 rotationTiltSpeed: 5 RotationTiltReturnSpeed: 3 @@ -132,6 +131,9 @@ MonoBehaviour: randomWaveOffset: 0.5 waveUnitSpeed: 10 meshObjectName: Ship_Mesh + showDebugVisuals: 1 + debugLineLength: 5 + debugLineWidth: 0.1 --- !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 af37b2d01..70012c929 100644 --- a/Assets/0_Voyage/_Scripts/Ship/VoyagePlayerShipMovement.cs +++ b/Assets/0_Voyage/_Scripts/Ship/VoyagePlayerShipMovement.cs @@ -7,31 +7,21 @@ public class VoyagePlayerShipMovement : MonoBehaviour [Header("Movement Settings")] [SerializeField] private float maxSpeed = 20f; [SerializeField] private float rotationSpeed = 180f; + [SerializeField] private float minRotationSpeed = 60f; + [SerializeField] private float rotationAccelerationRate = 5f; [SerializeField] private float accelerationRate = 1f; [SerializeField] private float minSpeedThreshold = 0.1f; [SerializeField] private float dragFactor = 0.98f; - private Vector3 currentVelocity; - private Vector2 currentInput; - private float targetSpeed; - private float currentSpeed; + private Vector3 _currentVelocity; + private Vector2 _currentInput; + private float _currentRotationSpeed; + private float _targetSpeed; + private float _currentSpeed; [Header("Turn Settings")] [SerializeField] private float turnSpeedPenalty = 0.5f; // 선회 시 감속 정도 (0: 감속 없음, 1: 완전 정지) [SerializeField] private float maxTurnAngle = 180f; // 최대 감속이 적용되는 각도 -#if UNITY_EDITOR - [Header("Debug Settings")] - [SerializeField] private bool showDebugLines = true; - - [SerializeField] private float debugLineLength = 4f; - [SerializeField] private float debugLineHeightStep = 0.1f; - private LineRenderer velocityLine; - private LineRenderer forwardDirectionLine; - private LineRenderer upDirectionLine; - private LineRenderer inputDirectionLine; - private bool lineRendererCreated = false; -#endif - // Rotation Tilt [Header("Rotation Tilt Settings")] [SerializeField] private float maxRotationTiltAngle = 15f; @@ -65,7 +55,7 @@ public class VoyagePlayerShipMovement : MonoBehaviour [SerializeField] private float waveUnitSpeed = 10f; // 기준 속력 private float _waveTime; private float _waveRandomOffset; - private float currentWaveHeight; + private float _currentWaveHeight; [Header("Mesh Settings")] @@ -91,11 +81,15 @@ public class VoyagePlayerShipMovement : MonoBehaviour _lastRotationY = transform.eulerAngles.y; _waveTime = 0f; _waveRandomOffset = Random.Range(-randomWaveOffset, randomWaveOffset); + +#if UNITY_EDITOR + InitializeDebugVisuals(); +#endif } private void FixedUpdate() { - if (currentInput.magnitude > minSpeedThreshold) + if (_currentInput.magnitude > minSpeedThreshold) { HandleMovement(); HandleRotation(); @@ -103,7 +97,8 @@ public class VoyagePlayerShipMovement : MonoBehaviour else { // 입력이 없을 때는 서서히 감속 - currentSpeed = Mathf.Lerp(currentSpeed, 0f, accelerationRate * Time.fixedDeltaTime); + _currentSpeed = Mathf.Lerp(_currentSpeed, 0f, accelerationRate * Time.fixedDeltaTime); + _currentRotationSpeed = 0; } ApplyDrag(); ApplyMovement(); @@ -117,20 +112,17 @@ public class VoyagePlayerShipMovement : MonoBehaviour ApplyMeshOffset(); #if UNITY_EDITOR - if (showDebugLines) - { - UpdateAllDebugLines(); - } + UpdateDebugVisuals(); #endif } private void HandleMovement() { // 기본 목표 속도 계산 (입력 크기에 비례) - float baseTargetSpeed = Mathf.Clamp01(currentInput.magnitude) * maxSpeed; + float baseTargetSpeed = Mathf.Clamp01(_currentInput.magnitude) * maxSpeed; // 현재 방향과 목표 방향 사이의 각도 계산 - Vector3 inputDirection = new Vector3(currentInput.x, 0, currentInput.y).normalized; + Vector3 inputDirection = new Vector3(_currentInput.x, 0, _currentInput.y).normalized; float angleDifference = Vector3.Angle(transform.forward, inputDirection); // 각도에 따른 속도 페널티 계산 (각도가 클수록 더 큰 감속) @@ -138,37 +130,38 @@ public class VoyagePlayerShipMovement : MonoBehaviour turnPenaltyFactor = Mathf.Clamp01(turnPenaltyFactor); // 최종 목표 속도 계산 (기본 속도에 선회 페널티 적용) - targetSpeed = baseTargetSpeed * turnPenaltyFactor; + _targetSpeed = baseTargetSpeed * turnPenaltyFactor; // 현재 속도를 목표 속도로 부드럽게 보간 - currentSpeed = Mathf.Lerp(currentSpeed, targetSpeed, accelerationRate * Time.fixedDeltaTime); + _currentSpeed = Mathf.Lerp(_currentSpeed, _targetSpeed, accelerationRate * Time.fixedDeltaTime); // 최소 임계값 이하면 완전히 정지 - if (currentSpeed < minSpeedThreshold && targetSpeed < minSpeedThreshold) + if (_currentSpeed < minSpeedThreshold && _targetSpeed < minSpeedThreshold) { - currentSpeed = 0f; + _currentSpeed = 0f; } // 현재 바라보는 방향으로 속도 벡터 업데이트 - currentVelocity = transform.forward * currentSpeed; + _currentVelocity = transform.forward * _currentSpeed; } private void HandleRotation() { - if (currentInput.magnitude > minSpeedThreshold) + if (_currentInput.magnitude > minSpeedThreshold) { - Vector3 inputDirection = new Vector3(currentInput.x, 0, currentInput.y).normalized; + Vector3 inputDirection = new Vector3(_currentInput.x, 0, _currentInput.y).normalized; Quaternion targetRotation = Quaternion.LookRotation(inputDirection, Vector3.up); // 회전 속도를 현재 속도에 비례하도록 설정 - float currentRotationSpeed = rotationSpeed * (currentSpeed / maxSpeed); - currentRotationSpeed = Mathf.Max(currentRotationSpeed, rotationSpeed * 0.3f); + 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 + _currentRotationSpeed * Time.fixedDeltaTime ); } } @@ -203,7 +196,7 @@ public class VoyagePlayerShipMovement : MonoBehaviour private void UpdateAccelerationTilt() { // 가속도 계산 - float acceleration = (currentSpeed - _prevSpeed) / Time.fixedDeltaTime; + float acceleration = (_currentSpeed - _prevSpeed) / Time.fixedDeltaTime; // 스프링 물리 시스템 구현 float springForce = -springStiffness * _currentAccelTilt; // 복원력 @@ -225,7 +218,7 @@ public class VoyagePlayerShipMovement : MonoBehaviour _currentAccelTilt = Mathf.Lerp(_currentAccelTilt, _currentAccelTilt + _accelTiltVelocity, accelTiltSpeed * Time.fixedDeltaTime); _currentAccelTilt = Mathf.Clamp(_currentAccelTilt, -maxAccelTiltAngle, maxAccelTiltAngle); - _prevSpeed = currentSpeed; + _prevSpeed = _currentSpeed; } private void ApplyMeshTilt() @@ -246,108 +239,48 @@ public class VoyagePlayerShipMovement : MonoBehaviour if (_meshTransform is null) return; // 현재 속도에 비례하여 파도 주기 조절 - float waveSpeedFactor = 1f + (currentSpeed / waveUnitSpeed) * speedWaveMultiplier; + float waveSpeedFactor = 1f + (_currentSpeed / waveUnitSpeed) * speedWaveMultiplier; _waveTime += Time.fixedDeltaTime * baseWaveFrequency * waveSpeedFactor; - float currentSpeedByUnit = currentSpeed / waveUnitSpeed; + float currentSpeedByUnit = _currentSpeed / waveUnitSpeed; currentSpeedByUnit = Mathf.Clamp01(currentSpeedByUnit); float waveHeight = Mathf.Lerp(minSpeedWaveHeight, maxSpeedWaveHeight, currentSpeedByUnit); - currentWaveHeight = waveHeight * Mathf.Sin(_waveTime + _waveRandomOffset); + _currentWaveHeight = waveHeight * Mathf.Sin(_waveTime + _waveRandomOffset); } private void ApplyMeshOffset() { if (_meshTransform is null) return; - Vector3 position = _originalMeshPosition + (Vector3.up * currentWaveHeight); + Vector3 position = _originalMeshPosition + (Vector3.up * _currentWaveHeight); _meshTransform.localPosition = position; } private void ApplyDrag() { - currentSpeed *= dragFactor; + _currentSpeed *= dragFactor; // 최소 속도 이하면 완전히 정지 - if (currentSpeed < minSpeedThreshold) + if (_currentSpeed < minSpeedThreshold) { - currentSpeed = 0f; + _currentSpeed = 0f; } // 현재 방향으로 감속된 속도 적용 - currentVelocity = transform.forward * currentSpeed; + _currentVelocity = transform.forward * _currentSpeed; } private void ApplyMovement() { - transform.position += currentVelocity * Time.fixedDeltaTime; + transform.position += _currentVelocity * Time.fixedDeltaTime; } public void OnMove(InputAction.CallbackContext context) { - currentInput = context.ReadValue(); + _currentInput = context.ReadValue(); } - -#if UNITY_EDITOR - private void UpdateAllDebugLines() - { - if (lineRendererCreated == false) - { - lineRendererCreated = true; - forwardDirectionLine = CreateLineRenderer("CurrentDirectionLine", Color.green); - upDirectionLine = CreateLineRenderer("UpDirectionLine", Color.yellow); - inputDirectionLine = CreateLineRenderer("InputDirectionLine", Color.red); - velocityLine = CreateLineRenderer("VelocityLine", Color.blue); - } - - // 전방 방향 표시 (기본 높이) - DrawDebugLine(forwardDirectionLine, transform.forward, debugLineLength, 0); - - // 메시의 위쪽 방향 표시 (틸팅 반영) - if (_meshTransform is not null) - { - DrawDebugLine(upDirectionLine, _meshTransform.up, debugLineLength, debugLineHeightStep); - } - - // 입력 방향 표시 (두 단계 위) - Vector3 inputDirection = new Vector3(currentInput.x, 0, currentInput.y).normalized; - DrawDebugLine(inputDirectionLine, inputDirection, debugLineLength * currentInput.magnitude, debugLineHeightStep * 2); - - // 속도 벡터 표시 (세 단계 위) - DrawDebugLine(velocityLine, currentVelocity.normalized, currentVelocity.magnitude, debugLineHeightStep * 3); - } - - private LineRenderer CreateLineRenderer(string name, Color color) - { - GameObject lineObj = new GameObject(name); - lineObj.transform.SetParent(transform); - LineRenderer line = lineObj.AddComponent(); - - line.startWidth = 0.1f; - line.endWidth = 0.1f; - line.material = new Material(Shader.Find("Universal Render Pipeline/Unlit")); - line.startColor = color; - line.endColor = color; - line.positionCount = 2; - - // 라인 렌더러가 다른 오브젝트를 가리지 않도록 설정 - line.shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.Off; - line.receiveShadows = false; - line.material.color = color; - - return line; - } - - private void DrawDebugLine(LineRenderer renderer, Vector3 direction, float length, float heightOffset) - { - if (!renderer) return; - - Vector3 position = transform.position + Vector3.up * heightOffset; - renderer.SetPosition(0, position); - renderer.SetPosition(1, position + direction * length); - } -#endif - + private void OnValidate() { // 에디터에서 메시 오브젝트 이름이 변경될 때 자동으로 찾기 @@ -356,4 +289,188 @@ public class VoyagePlayerShipMovement : MonoBehaviour _meshTransform = transform.Find(meshObjectName); } } + + +#if UNITY_EDITOR + [Header("Debug Visualization")] + [SerializeField] private bool showDebugVisuals = true; + [SerializeField] private float debugLineLength = 5f; + [SerializeField] private float debugLineWidth = 0.1f; + + private LineRenderer _speedLineRenderer; + private LineRenderer _rotationSpeedLineRenderer; + private LineRenderer _rotationDeltaLineRenderer; + private LineRenderer _TiltLineRenderer; + private LineRenderer _waveHeightLineRenderer; + private LineRenderer _wavePatternLineRenderer; + +private void InitializeDebugVisuals() +{ + 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; // 파도 패턴을 위한 더 많은 점 +} + +private void UpdateDebugVisuals() +{ + if (!showDebugVisuals) return; + + // 속도 벡터 표시 + UpdateSpeedLine(); + + // 회전 방향 및 각속도 표시 + UpdateRotationSpeedLine(); + UpdateRotationDeltaLine(); + // 회전 틸트 표시 + UpdateTiltLine(); + // 파도 높이와 패턴 표시 + UpdateWaveVisualization(); +} + +private void UpdateSpeedLine() +{ + Vector3 start = transform.position + Vector3.up * 1.5f; + Vector3 end = start + transform.forward * (_currentSpeed / maxSpeed) * debugLineLength * 2; + DrawLine(_speedLineRenderer, start, end); +} + +private void UpdateRotationSpeedLine() +{ + Vector3 start = transform.position + Vector3.up * 1.2f; + // 각속도를 호로 표현 + if (Mathf.Abs(_currentRotationSpeed) > 0.1f) + { + Vector3[] arcPoints = new Vector3[10]; + float radius = debugLineLength * 1f; + float angleStep = _currentRotationSpeed * 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; + } +} + +private void UpdateRotationDeltaLine() +{ + float deltaAngle = 0f; + if (_currentInput.magnitude > minSpeedThreshold) + { + Vector3 inputDirection = new Vector3(_currentInput.x, 0, _currentInput.y).normalized; + Quaternion targetRotation = Quaternion.LookRotation(inputDirection, Vector3.up); + deltaAngle = Quaternion.Angle(transform.rotation, targetRotation); + } + + 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); + + 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 + { + _rotationDeltaLineRenderer.positionCount = 0; + } +} + +private void UpdateTiltLine() +{ + Vector3 start = transform.position + Vector3.up * 1.5f; + Vector3 tiltDirection = _meshTransform.up; + DrawLine(_TiltLineRenderer, start, start + tiltDirection * debugLineLength * 0.4f); +} + +private void UpdateWaveVisualization() +{ + // 현재 파도 높이 표시 + Vector3 waveStart = transform.position + Vector3.up*1.5f - transform.forward*1.5f; + Vector3 waveEnd = waveStart + Vector3.up * _currentWaveHeight * debugLineLength; + DrawLine(_waveHeightLineRenderer, waveStart, waveEnd); + + // 파도 패턴 시각화 + Vector3[] wavePoints = new Vector3[_wavePatternLineRenderer.positionCount]; + float waveLength = debugLineLength * 2f; + + for (int i = 0; i < wavePoints.Length; i++) + { + float t = (float)i / (_wavePatternLineRenderer.positionCount - 1); + float x = t * waveLength - waveLength * 0.5f; + float currentSpeedByUnit = _currentSpeed / waveUnitSpeed; + currentSpeedByUnit = Mathf.Clamp01(currentSpeedByUnit); + float waveHeight = Mathf.Lerp(minSpeedWaveHeight, maxSpeedWaveHeight, currentSpeedByUnit); + float y = Mathf.Sin((_waveTime + x) * baseWaveFrequency) * waveHeight; + + wavePoints[i] = transform.position + + Vector3.right * x + + Vector3.up * (y + 2f); // 높이 오프셋 + wavePoints[i] += Vector3.back * 3f + Vector3.down * 1f; + } + + _wavePatternLineRenderer.SetPositions(wavePoints); +} + +private LineRenderer CreateLineRenderer(string name, Color color) +{ + GameObject lineObj = new GameObject(name); + lineObj.transform.SetParent(transform); + LineRenderer line = lineObj.AddComponent(); + + line.startWidth = debugLineWidth; + line.endWidth = debugLineWidth; + line.material = new Material(Shader.Find("Universal Render Pipeline/Unlit")); + line.startColor = color; + line.endColor = color; + line.positionCount = 2; + + 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 == null) return; + line.positionCount = 2; + line.SetPosition(0, start); + line.SetPosition(1, end); +} + + +#endif + } \ No newline at end of file