diff --git a/Assets/0_Voyage/Ship/Player/PlayerShip.prefab b/Assets/0_Voyage/Ship/Player/PlayerShip.prefab
index 69715f9e6..de2a26ea0 100644
--- a/Assets/0_Voyage/Ship/Player/PlayerShip.prefab
+++ b/Assets/0_Voyage/Ship/Player/PlayerShip.prefab
@@ -106,17 +106,17 @@ MonoBehaviour:
m_Name:
m_EditorClassIdentifier:
maxSpeed: 20
- rotationSpeed: 180
- minRotationSpeed: 60
- rotationAccelerationRate: 5
accelerationRate: 1
- minSpeedThreshold: 0.1
dragFactor: 0.98
+ minSpeedThreshold: 0.1
+ rotationSpeed: 270
+ minRotationSpeed: 90
+ rotationAccelerationRate: 5
turnSpeedPenalty: 0.5
maxTurnAngle: 180
maxRotationTiltAngle: 15
rotationTiltSpeed: 5
- RotationTiltReturnSpeed: 3
+ rotationTiltReturnSpeed: 3
angularVelocityMultiplier: 2
maxAccelTiltAngle: 15
accelTiltForce: 15
@@ -130,7 +130,7 @@ MonoBehaviour:
speedWaveMultiplier: 5
randomWaveOffset: 0.5
waveUnitSpeed: 10
- meshObjectName: Ship_Mesh
+ meshTransform: {fileID: 2507610487897935131}
showDebugVisuals: 1
debugLineLength: 5
debugLineWidth: 0.1
diff --git a/Assets/0_Voyage/_Scripts/Ship/VoyagePlayerShipMovement.cs b/Assets/0_Voyage/_Scripts/Ship/VoyagePlayerShipMovement.cs
index 70012c929..95691d6f5 100644
--- a/Assets/0_Voyage/_Scripts/Ship/VoyagePlayerShipMovement.cs
+++ b/Assets/0_Voyage/_Scripts/Ship/VoyagePlayerShipMovement.cs
@@ -1,87 +1,90 @@
using UnityEngine;
using UnityEngine.InputSystem;
-using UnityEngine.Serialization;
+///
+/// 플레이어 배의 움직임을 제어하는 컴포넌트
+/// 속도, 회전, 틸트, 파도 효과 등을 관리합니다.
+///
public class VoyagePlayerShipMovement : MonoBehaviour
{
- [Header("Movement Settings")]
+ #region Inspector Fields
+
+ [Header("기본 이동 설정")]
+ [Tooltip("배의 최대 이동 속도")]
[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 _currentRotationSpeed;
- private float _targetSpeed;
- private float _currentSpeed;
-
- [Header("Turn Settings")]
- [SerializeField] private float turnSpeedPenalty = 0.5f; // 선회 시 감속 정도 (0: 감속 없음, 1: 완전 정지)
- [SerializeField] private float maxTurnAngle = 180f; // 최대 감속이 적용되는 각도
-
- // Rotation Tilt
- [Header("Rotation Tilt Settings")]
+ [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;
+
+ [Header("회전 틸트 설정")]
[SerializeField] private float maxRotationTiltAngle = 15f;
[SerializeField] private float rotationTiltSpeed = 5f;
- [SerializeField] private float RotationTiltReturnSpeed = 3f; // 원래 자세로 돌아오는 속도
- [SerializeField] private float angularVelocityMultiplier = 2f; // 각속도 영향력
- private float _currentRotationTilt = 0f;
- private float _lastRotationY; // 이전 프레임의 Y축 회전값
- private float _currentAngularVelocity; // 현재 각속도
+ [SerializeField] private float rotationTiltReturnSpeed = 3f;
+ [SerializeField] private float angularVelocityMultiplier = 2f;
- // Acceleration Tilt
- [Header("Acceleration Tilt Settings")]
- [SerializeField] private float maxAccelTiltAngle = 15f; // 최대 가속 틸트 각도
- [SerializeField] private float accelTiltForce = 15f; // 틸트 강도
- [SerializeField] private float accelTiltDamping = 0.9f; // 틸트 감쇠 계수
- [SerializeField] private float accelTiltSpeed = 10f; // 스프링 보간속도
- [SerializeField] private float springStiffness = 30f; // 스프링 강성
- [SerializeField] private float springDamping = 15f; // 스프링 감쇠
- private float _currentAccelTilt;
- private float _accelTiltVelocity;
- private float _prevSpeed;
-
- // Wave offset
- [Header("Wave Settings")]
- [SerializeField] private float minSpeedWaveHeight = 0.2f; // 기본 파도 높이
- [SerializeField] private float maxSpeedWaveHeight = 0.05f; // 기준 속력일때 파도 높이
-
- [SerializeField] private float baseWaveFrequency = 1f; // 기본 파도 주기
- [SerializeField] private float speedWaveMultiplier = 5f; // 속도에 따른 주기 증가 계수
- [SerializeField] private float randomWaveOffset = 0.5f; // 랜덤 오프셋 범위
- [SerializeField] private float waveUnitSpeed = 10f; // 기준 속력
- private float _waveTime;
- private float _waveRandomOffset;
- private float _currentWaveHeight;
+ [Header("가속 틸트 설정")]
+ [SerializeField] private float maxAccelTiltAngle = 15f;
+ [SerializeField] private float accelTiltForce = 15f;
+ [SerializeField] private float accelTiltDamping = 0.9f;
+ [SerializeField] private float accelTiltSpeed = 10f;
+ [SerializeField] private float springStiffness = 30f;
+ [SerializeField] private float springDamping = 15f;
+
+ [Header("파도 효과 설정")]
+ [SerializeField] private float minSpeedWaveHeight = 0.2f;
+ [SerializeField] private float maxSpeedWaveHeight = 0.05f;
+ [SerializeField] private float baseWaveFrequency = 1f;
+ [SerializeField] private float speedWaveMultiplier = 5f;
+ [SerializeField] private float randomWaveOffset = 0.5f;
+ [SerializeField] private float waveUnitSpeed = 10f;
+
+ [Header("메시 설정")]
+ [SerializeField] private Transform meshTransform;
+
+ #endregion
+
+ #region Private Fields
+
+ private Vector3 currentVelocity;
+ private Vector2 currentInput;
+ private float currentRotationSpeed;
+ private float targetSpeed;
+ private float currentSpeed;
+
+ // 회전 틸트 관련
+ 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;
+
+ // 메시 원본 상태
+ private Quaternion originalMeshRotation;
+ private Vector3 originalMeshPosition;
+
+ #endregion
+
+ #region Unity Messages
-
- [Header("Mesh Settings")]
- [SerializeField] private string meshObjectName = "Ship_Mesh";
- private Transform _meshTransform;
-
-
- private Quaternion _originalMeshRotation;
- private Vector3 _originalMeshPosition;
-
private void Start()
{
- _meshTransform = transform.Find(meshObjectName);
- if (_meshTransform == null)
- {
- Debug.LogError($"메시 오브젝트를 찾을 수 없습니다: {meshObjectName}");
- enabled = false;
- return;
- }
-
- _originalMeshPosition = _meshTransform.localPosition;
- _originalMeshRotation = _meshTransform.localRotation;
- _lastRotationY = transform.eulerAngles.y;
- _waveTime = 0f;
- _waveRandomOffset = Random.Range(-randomWaveOffset, randomWaveOffset);
-
+ InitializeMeshTransform();
+ InitializeWaveEffect();
#if UNITY_EDITOR
InitializeDebugVisuals();
#endif
@@ -89,118 +92,154 @@ public class VoyagePlayerShipMovement : MonoBehaviour
private void FixedUpdate()
{
- if (_currentInput.magnitude > minSpeedThreshold)
+ UpdateMovement();
+ UpdateVisualEffects();
+#if UNITY_EDITOR
+ UpdateDebugVisuals();
+#endif
+ }
+
+ private void OnValidate()
+ {
+ ValidateMeshTransform();
+ }
+
+ #endregion
+
+ #region Movement Methods
+
+ private void UpdateMovement()
+ {
+ if (IsMoving())
{
HandleMovement();
HandleRotation();
}
else
{
- // 입력이 없을 때는 서서히 감속
- _currentSpeed = Mathf.Lerp(_currentSpeed, 0f, accelerationRate * Time.fixedDeltaTime);
- _currentRotationSpeed = 0;
+ DecelerateMovement();
}
+
ApplyDrag();
ApplyMovement();
+ }
- // Cosmetic mesh tilting
- UpdateMeshRotationTilt();
- UpdateAccelerationTilt();
- ApplyMeshTilt();
- // Cosmetic mesh wave offset
- UpdateWaveMotion();
- ApplyMeshOffset();
-
-#if UNITY_EDITOR
- UpdateDebugVisuals();
-#endif
+ private bool IsMoving()
+ {
+ return currentInput.magnitude > minSpeedThreshold;
}
private void HandleMovement()
{
- // 기본 목표 속도 계산 (입력 크기에 비례)
- float baseTargetSpeed = Mathf.Clamp01(_currentInput.magnitude) * maxSpeed;
+ float baseTargetSpeed = CalculateBaseTargetSpeed();
+ float turnPenaltyFactor = CalculateTurnPenaltyFactor();
+
+ targetSpeed = baseTargetSpeed * turnPenaltyFactor;
+ currentSpeed = Mathf.Lerp(currentSpeed, targetSpeed, accelerationRate * Time.fixedDeltaTime);
- // 현재 방향과 목표 방향 사이의 각도 계산
- Vector3 inputDirection = new Vector3(_currentInput.x, 0, _currentInput.y).normalized;
- float angleDifference = Vector3.Angle(transform.forward, inputDirection);
-
- // 각도에 따른 속도 페널티 계산 (각도가 클수록 더 큰 감속)
- float turnPenaltyFactor = 1f - (angleDifference / maxTurnAngle * turnSpeedPenalty);
- turnPenaltyFactor = Mathf.Clamp01(turnPenaltyFactor);
-
- // 최종 목표 속도 계산 (기본 속도에 선회 페널티 적용)
- _targetSpeed = baseTargetSpeed * turnPenaltyFactor;
-
- // 현재 속도를 목표 속도로 부드럽게 보간
- _currentSpeed = Mathf.Lerp(_currentSpeed, _targetSpeed, accelerationRate * Time.fixedDeltaTime);
-
- // 최소 임계값 이하면 완전히 정지
- if (_currentSpeed < minSpeedThreshold && _targetSpeed < minSpeedThreshold)
+ if (ShouldStop())
{
- _currentSpeed = 0f;
+ currentSpeed = 0f;
}
- // 현재 바라보는 방향으로 속도 벡터 업데이트
- _currentVelocity = transform.forward * _currentSpeed;
+ UpdateVelocityVector();
+ }
+
+ private float CalculateBaseTargetSpeed()
+ {
+ return Mathf.Clamp01(currentInput.magnitude) * 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));
+ }
+
+ private bool ShouldStop()
+ {
+ return currentSpeed < minSpeedThreshold && targetSpeed < minSpeedThreshold;
+ }
+
+ private void UpdateVelocityVector()
+ {
+ currentVelocity = transform.forward * currentSpeed;
+ }
+
+ #endregion
+
+ #region Visual Effects
+
+ private void UpdateVisualEffects()
+ {
+ if (meshTransform is null) return;
+
+ UpdateMeshRotationTilt();
+ UpdateAccelerationTilt();
+ ApplyMeshTilt();
+ UpdateWaveMotion();
+ ApplyMeshOffset();
}
private void HandleRotation()
{
- if (_currentInput.magnitude > minSpeedThreshold)
+ if (IsMoving())
{
- 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 desiredRotationSpeed = rotationSpeed * (_currentSpeed / maxSpeed);
+ float desiredRotationSpeed = rotationSpeed * (currentSpeed / maxSpeed);
desiredRotationSpeed = Mathf.Max(desiredRotationSpeed, minRotationSpeed);
- _currentRotationSpeed = Mathf.Lerp(_currentRotationSpeed, desiredRotationSpeed, rotationAccelerationRate * Time.fixedDeltaTime);
-
+ currentRotationSpeed = Mathf.Lerp(currentRotationSpeed, desiredRotationSpeed,
+ rotationAccelerationRate * Time.fixedDeltaTime);
+
// 기본 회전 적용 (오브젝트 전체)
transform.rotation = Quaternion.RotateTowards(
transform.rotation,
targetRotation,
- _currentRotationSpeed * Time.fixedDeltaTime
+ currentRotationSpeed * Time.fixedDeltaTime
);
}
}
private void UpdateMeshRotationTilt()
{
- if (_meshTransform is null) return;
+ if (meshTransform is null) return;
// 현재 Y축 회전값과 각속도 계산
float currentRotationY = transform.eulerAngles.y;
- float deltaRotation = Mathf.DeltaAngle(_lastRotationY, currentRotationY);
- _currentAngularVelocity = deltaRotation / Time.fixedDeltaTime;
+ float deltaRotation = Mathf.DeltaAngle(lastRotationY, currentRotationY);
+ currentAngularVelocity = deltaRotation / Time.fixedDeltaTime;
// 목표 틸트 각도 계산
- float targetTilt = -_currentAngularVelocity * angularVelocityMultiplier;
+ float targetTilt = -currentAngularVelocity * angularVelocityMultiplier;
targetTilt = Mathf.Clamp(targetTilt, -maxRotationTiltAngle, maxRotationTiltAngle);
// 틸트 적용 또는 복귀
- if (Mathf.Abs(_currentAngularVelocity) > 0.1f)
+ if (Mathf.Abs(currentAngularVelocity) > 0.1f)
{
- _currentRotationTilt = Mathf.Lerp(_currentRotationTilt, targetTilt, rotationTiltSpeed * Time.fixedDeltaTime);
+ currentRotationTilt =
+ Mathf.Lerp(currentRotationTilt, targetTilt, rotationTiltSpeed * Time.fixedDeltaTime);
}
else
{
// 입력이 없을 때는 원래 자세로 천천히 복귀
- _currentRotationTilt = Mathf.Lerp(_currentRotationTilt, 0f, RotationTiltReturnSpeed * Time.fixedDeltaTime);
+ currentRotationTilt = Mathf.Lerp(currentRotationTilt, 0f, rotationTiltReturnSpeed * Time.fixedDeltaTime);
}
-
- _lastRotationY = currentRotationY;
+
+ lastRotationY = currentRotationY;
}
private void UpdateAccelerationTilt()
{
// 가속도 계산
- float acceleration = (_currentSpeed - _prevSpeed) / Time.fixedDeltaTime;
+ float acceleration = (currentSpeed - prevSpeed) / Time.fixedDeltaTime;
// 스프링 물리 시스템 구현
- float springForce = -springStiffness * _currentAccelTilt; // 복원력
- float dampingForce = -springDamping * _accelTiltVelocity; // 감쇠력
+ float springForce = -springStiffness * currentAccelTilt; // 복원력
+ float dampingForce = -springDamping * accelTiltVelocity; // 감쇠력
float accelerationForce = -acceleration * accelTiltForce; // 가속에 의한 힘
// 전체 힘 계산
@@ -210,90 +249,127 @@ public class VoyagePlayerShipMovement : MonoBehaviour
float tiltAcceleration = totalForce;
// 속도 업데이트
- _accelTiltVelocity += tiltAcceleration;
- _accelTiltVelocity *= accelTiltDamping; // 감쇠 적용
- _accelTiltVelocity *= Time.fixedDeltaTime;
+ accelTiltVelocity += tiltAcceleration;
+ accelTiltVelocity *= accelTiltDamping; // 감쇠 적용
+ accelTiltVelocity *= Time.fixedDeltaTime;
// 위치(각도) 업데이트
- _currentAccelTilt = Mathf.Lerp(_currentAccelTilt, _currentAccelTilt + _accelTiltVelocity, accelTiltSpeed * Time.fixedDeltaTime);
- _currentAccelTilt = Mathf.Clamp(_currentAccelTilt, -maxAccelTiltAngle, maxAccelTiltAngle);
+ currentAccelTilt = Mathf.Lerp(currentAccelTilt, currentAccelTilt + accelTiltVelocity,
+ accelTiltSpeed * Time.fixedDeltaTime);
+ currentAccelTilt = Mathf.Clamp(currentAccelTilt, -maxAccelTiltAngle, maxAccelTiltAngle);
- _prevSpeed = _currentSpeed;
+ prevSpeed = currentSpeed;
}
private void ApplyMeshTilt()
{
- if (_meshTransform is null) return;
+ if (meshTransform is null) return;
// 회전 틸트와 가속 틸트를 조합
// 메시에 최종 틸트 적용
- _meshTransform.localRotation = _originalMeshRotation * Quaternion.Euler(
- _currentAccelTilt, // X축 (가속 틸트)
+ meshTransform.localRotation = originalMeshRotation * Quaternion.Euler(
+ currentAccelTilt, // X축 (가속 틸트)
0, // Y축
- _currentRotationTilt // Z축 (회전 틸트)
+ currentRotationTilt // Z축 (회전 틸트)
);
}
private void UpdateWaveMotion()
{
- if (_meshTransform is null) return;
-
+ if (meshTransform is null) return;
+
// 현재 속도에 비례하여 파도 주기 조절
- float waveSpeedFactor = 1f + (_currentSpeed / waveUnitSpeed) * speedWaveMultiplier;
- _waveTime += Time.fixedDeltaTime * baseWaveFrequency * waveSpeedFactor;
- float currentSpeedByUnit = _currentSpeed / waveUnitSpeed;
+ float waveSpeedFactor = 1f + (currentSpeed / waveUnitSpeed) * speedWaveMultiplier;
+ waveTime += Time.fixedDeltaTime * baseWaveFrequency * waveSpeedFactor;
+ 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;
+ if (meshTransform is null) return;
- Vector3 position = _originalMeshPosition + (Vector3.up * _currentWaveHeight);
- _meshTransform.localPosition = position;
+ 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;
}
+ private void DecelerateMovement()
+ {
+ // 입력이 없을 때는 서서히 감속
+ currentSpeed = Mathf.Lerp(currentSpeed, 0f, accelerationRate * Time.fixedDeltaTime);
+ currentRotationSpeed = 0;
+ }
+
+ #endregion
+
+ #region Input Handling
+
public void OnMove(InputAction.CallbackContext context)
{
- _currentInput = context.ReadValue();
+ currentInput = context.ReadValue();
}
-
- private void OnValidate()
+
+ #endregion
+
+ #region Initialization
+
+ private void InitializeMeshTransform()
{
- // 에디터에서 메시 오브젝트 이름이 변경될 때 자동으로 찾기
- if (Application.isEditor && !Application.isPlaying)
+ if (meshTransform is null)
{
- _meshTransform = transform.Find(meshObjectName);
+ Debug.LogError("Mesh Transform이 할당되지 않았습니다.");
+ enabled = false;
+ return;
+ }
+
+ originalMeshPosition = meshTransform.localPosition;
+ originalMeshRotation = meshTransform.localRotation;
+ lastRotationY = transform.eulerAngles.y;
+ }
+
+ private void InitializeWaveEffect()
+ {
+ waveTime = 0f;
+ waveRandomOffset = Random.Range(-randomWaveOffset, randomWaveOffset);
+ }
+
+ private void ValidateMeshTransform()
+ {
+ if (Application.isEditor && !Application.isPlaying && meshTransform is null)
+ {
+ Debug.LogWarning("Mesh Transform을 Inspector에서 할당해주세요.");
}
}
+ #endregion
#if UNITY_EDITOR
[Header("Debug Visualization")]
[SerializeField] private bool showDebugVisuals = true;
+
[SerializeField] private float debugLineLength = 5f;
[SerializeField] private float debugLineWidth = 0.1f;
@@ -304,173 +380,170 @@ public class VoyagePlayerShipMovement : MonoBehaviour
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)
+ private void InitializeDebugVisuals()
{
- Vector3[] arcPoints = new Vector3[10];
- float radius = debugLineLength * 1f;
- float angleStep = _currentRotationSpeed * 1f / (arcPoints.Length - 1);
-
- for (int i = 0; i < arcPoints.Length; i++)
+ 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)
{
- float angle = angleStep * i;
- Vector3 point = start + Quaternion.Euler(0, angle, 0) * transform.forward * radius;
- arcPoints[i] = point;
+ 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);
}
-
- _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++)
+ else
{
- float angle = angleStep * i;
- Vector3 point = start + Quaternion.Euler(0, angle, 0) * transform.forward * radius;
- arcPoints[i] = point;
+ _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);
}
- _rotationDeltaLineRenderer.positionCount = arcPoints.Length;
- _rotationDeltaLineRenderer.SetPositions(arcPoints);
+ 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;
+ }
}
- else
+
+ private void UpdateTiltLine()
{
- _rotationDeltaLineRenderer.positionCount = 0;
+ Vector3 start = transform.position + Vector3.up * 1.5f;
+ Vector3 tiltDirection = meshTransform.up;
+ DrawLine(_TiltLineRenderer, start, start + tiltDirection * debugLineLength * 0.4f);
}
-}
-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++)
+ private void UpdateWaveVisualization()
{
- 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;
+ // 현재 파도 높이 표시
+ 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);
}
-
- _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 LineRenderer CreateLineRenderer(string name, Color color)
+ {
+ GameObject lineObj = new GameObject(name);
+ lineObj.transform.SetParent(transform);
+ LineRenderer line = lineObj.AddComponent();
-private void DrawLine(LineRenderer line, Vector3 start, Vector3 end)
-{
- if (line == null) return;
- line.positionCount = 2;
- line.SetPosition(0, start);
- line.SetPosition(1, end);
-}
+ 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 is null) return;
+ line.positionCount = 2;
+ line.SetPosition(0, start);
+ line.SetPosition(1, end);
+ }
#endif
-
}
\ No newline at end of file