using UnityEngine; namespace Voyage { #if UNITY_EDITOR /// /// 배의 움직임을 시각적으로 디버깅하기 위한 컴포넌트 /// [RequireComponent(typeof(VoyagePlayerShipMovement))] [RequireComponent(typeof(VoyagePlayerShipMovementVisual))] public class VoyagePlayerShipDebug : MonoBehaviour { #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; } [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 (!settings.showDebugVisuals) return; InitializeComponents(); InitializeDebugLines(); } private void Update() { if (!settings.showDebugVisuals) return; UpdateAllDebugLines(); } #endregion #region Initialization private void InitializeComponents() { movement = GetComponent(); movementVisual = GetComponent(); } private void InitializeDebugLines() { 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 #region Line Updates private void UpdateAllDebugLines() { UpdateSpeedLine(); UpdateRotationLines(); UpdateTiltLine(); UpdateWaveVisualization(); } private void UpdateSpeedLine() { 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 UpdateRotationLines() { UpdateRotationSpeedArc(); UpdateRotationDeltaArc(); } private void UpdateRotationSpeedArc() { if (Mathf.Abs(movement.CurrentRotationSpeed) <= 0.1f) { lines.RotationSpeed.positionCount = 0; return; } DrawArc(lines.RotationSpeed, GetDebugLineStart(1.2f), settings.lineLength, movement.CurrentRotationSpeed); } private void UpdateRotationDeltaArc() { if (movement.CurrentInput.magnitude <= 0.1f) { 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 = GetDebugLineStart(1.5f); Vector3 tiltDirection = movementVisual.MeshTransform.up; 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 * (movementVisual.CurrentWaveHeight * settings.lineLength); DrawLine(lines.WaveHeight, waveStart, waveEnd); } private void UpdateWavePatternLine() { // 파도 패턴 시각화 Vector3[] wavePoints = new Vector3[lines.WavePattern.positionCount]; float waveLength = settings.lineLength * 2f; for (int i = 0; i < wavePoints.Length; i++) { float t = (float)i / (lines.WavePattern.positionCount - 1); float x = t * waveLength - waveLength * 0.5f; float currentSpeedByUnit = movement.CurrentSpeed / movementVisual.WaveUnitSpeed; currentSpeedByUnit = Mathf.Clamp01(currentSpeedByUnit); 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 + Vector3.up * (y + 2f); // 높이 오프셋 wavePoints[i] += Vector3.back * 3f + Vector3.down * 1f; } lines.WavePattern.SetPositions(wavePoints); } #endregion #region Helper Methods private Vector3 GetDebugLineStart(float heightOffset) { return transform.position + Vector3.up * heightOffset; } private float CalculateRotationDeltaAngle() { 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; } 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 = line.endColor = color; line.positionCount = pointCount; line.shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.Off; line.receiveShadows = false; line.material.color = color; } 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 }