DDD-43 디버그 기능 추가

This commit is contained in:
Jeonghyeon Ha 2025-07-15 19:13:50 +09:00
parent 241a2fc51d
commit d03a4b7892
3 changed files with 303 additions and 140 deletions

View File

@ -90187,8 +90187,8 @@ Transform:
m_PrefabAsset: {fileID: 0} m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 943285313} m_GameObject: {fileID: 943285313}
serializedVersion: 2 serializedVersion: 2
m_LocalRotation: {x: 0.22409342, y: 0, z: 0, w: 0.97456765} m_LocalRotation: {x: 0.25884834, y: 0, z: 0, w: 0.965918}
m_LocalPosition: {x: 0, y: 8.74, z: -18} m_LocalPosition: {x: 0, y: 11.014116, z: -19.074339}
m_LocalScale: {x: 1, y: 1, z: 1} m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0 m_ConstrainProportionsScale: 0
m_Children: [] m_Children: []
@ -141074,7 +141074,7 @@ Transform:
m_PrefabAsset: {fileID: 0} m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1413354196} m_GameObject: {fileID: 1413354196}
serializedVersion: 2 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_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1} m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0 m_ConstrainProportionsScale: 0
@ -152373,8 +152373,8 @@ GameObject:
m_Component: m_Component:
- component: {fileID: 1498712852} - component: {fileID: 1498712852}
- component: {fileID: 1498712855} - component: {fileID: 1498712855}
- component: {fileID: 1498712854} - component: {fileID: 1498712857}
- component: {fileID: 1498712856} - component: {fileID: 1498712858}
m_Layer: 9 m_Layer: 9
m_Name: CinemachineCamera_Back m_Name: CinemachineCamera_Back
m_TagString: Untagged m_TagString: Untagged
@ -152390,32 +152390,13 @@ Transform:
m_PrefabAsset: {fileID: 0} m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1498712851} m_GameObject: {fileID: 1498712851}
serializedVersion: 2 serializedVersion: 2
m_LocalRotation: {x: 0.22409342, y: 0, z: 0, w: 0.97456765} m_LocalRotation: {x: 0.25884834, y: 0, z: 0, w: 0.965918}
m_LocalPosition: {x: 0, y: 8.74, z: -18} m_LocalPosition: {x: 0, y: 11.014116, z: -19.074339}
m_LocalScale: {x: 1, y: 1, z: 1} m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0 m_ConstrainProportionsScale: 0
m_Children: [] m_Children: []
m_Father: {fileID: 1885259736} m_Father: {fileID: 1885259736}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} 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 --- !u!114 &1498712855
MonoBehaviour: MonoBehaviour:
m_ObjectHideFlags: 0 m_ObjectHideFlags: 0
@ -152459,7 +152440,70 @@ MonoBehaviour:
BarrelClipping: 0.25 BarrelClipping: 0.25
Anamorphism: 0 Anamorphism: 0
BlendHint: 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: MonoBehaviour:
m_ObjectHideFlags: 0 m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0} m_CorrespondingSourceObject: {fileID: 0}
@ -154945,7 +154989,7 @@ Transform:
m_GameObject: {fileID: 1528083691} m_GameObject: {fileID: 1528083691}
serializedVersion: 2 serializedVersion: 2
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} 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_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0 m_ConstrainProportionsScale: 0
m_Children: m_Children:

View File

@ -107,14 +107,13 @@ MonoBehaviour:
m_EditorClassIdentifier: m_EditorClassIdentifier:
maxSpeed: 20 maxSpeed: 20
rotationSpeed: 180 rotationSpeed: 180
minRotationSpeed: 60
rotationAccelerationRate: 5
accelerationRate: 1 accelerationRate: 1
minSpeedThreshold: 0.1 minSpeedThreshold: 0.1
dragFactor: 0.98 dragFactor: 0.98
turnSpeedPenalty: 0.5 turnSpeedPenalty: 0.5
maxTurnAngle: 180 maxTurnAngle: 180
showDebugLines: 1
debugLineLength: 5
debugLineHeightStep: 0.02
maxRotationTiltAngle: 15 maxRotationTiltAngle: 15
rotationTiltSpeed: 5 rotationTiltSpeed: 5
RotationTiltReturnSpeed: 3 RotationTiltReturnSpeed: 3
@ -132,6 +131,9 @@ MonoBehaviour:
randomWaveOffset: 0.5 randomWaveOffset: 0.5
waveUnitSpeed: 10 waveUnitSpeed: 10
meshObjectName: Ship_Mesh meshObjectName: Ship_Mesh
showDebugVisuals: 1
debugLineLength: 5
debugLineWidth: 0.1
--- !u!1 &6407855916708530114 --- !u!1 &6407855916708530114
GameObject: GameObject:
m_ObjectHideFlags: 0 m_ObjectHideFlags: 0

View File

@ -7,31 +7,21 @@ public class VoyagePlayerShipMovement : MonoBehaviour
[Header("Movement Settings")] [Header("Movement Settings")]
[SerializeField] private float maxSpeed = 20f; [SerializeField] private float maxSpeed = 20f;
[SerializeField] private float rotationSpeed = 180f; [SerializeField] private float rotationSpeed = 180f;
[SerializeField] private float minRotationSpeed = 60f;
[SerializeField] private float rotationAccelerationRate = 5f;
[SerializeField] private float accelerationRate = 1f; [SerializeField] private float accelerationRate = 1f;
[SerializeField] private float minSpeedThreshold = 0.1f; [SerializeField] private float minSpeedThreshold = 0.1f;
[SerializeField] private float dragFactor = 0.98f; [SerializeField] private float dragFactor = 0.98f;
private Vector3 currentVelocity; private Vector3 _currentVelocity;
private Vector2 currentInput; private Vector2 _currentInput;
private float targetSpeed; private float _currentRotationSpeed;
private float currentSpeed; private float _targetSpeed;
private float _currentSpeed;
[Header("Turn Settings")] [Header("Turn Settings")]
[SerializeField] private float turnSpeedPenalty = 0.5f; // 선회 시 감속 정도 (0: 감속 없음, 1: 완전 정지) [SerializeField] private float turnSpeedPenalty = 0.5f; // 선회 시 감속 정도 (0: 감속 없음, 1: 완전 정지)
[SerializeField] private float maxTurnAngle = 180f; // 최대 감속이 적용되는 각도 [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 // Rotation Tilt
[Header("Rotation Tilt Settings")] [Header("Rotation Tilt Settings")]
[SerializeField] private float maxRotationTiltAngle = 15f; [SerializeField] private float maxRotationTiltAngle = 15f;
@ -65,7 +55,7 @@ public class VoyagePlayerShipMovement : MonoBehaviour
[SerializeField] private float waveUnitSpeed = 10f; // 기준 속력 [SerializeField] private float waveUnitSpeed = 10f; // 기준 속력
private float _waveTime; private float _waveTime;
private float _waveRandomOffset; private float _waveRandomOffset;
private float currentWaveHeight; private float _currentWaveHeight;
[Header("Mesh Settings")] [Header("Mesh Settings")]
@ -91,11 +81,15 @@ public class VoyagePlayerShipMovement : MonoBehaviour
_lastRotationY = transform.eulerAngles.y; _lastRotationY = transform.eulerAngles.y;
_waveTime = 0f; _waveTime = 0f;
_waveRandomOffset = Random.Range(-randomWaveOffset, randomWaveOffset); _waveRandomOffset = Random.Range(-randomWaveOffset, randomWaveOffset);
#if UNITY_EDITOR
InitializeDebugVisuals();
#endif
} }
private void FixedUpdate() private void FixedUpdate()
{ {
if (currentInput.magnitude > minSpeedThreshold) if (_currentInput.magnitude > minSpeedThreshold)
{ {
HandleMovement(); HandleMovement();
HandleRotation(); HandleRotation();
@ -103,7 +97,8 @@ public class VoyagePlayerShipMovement : MonoBehaviour
else else
{ {
// 입력이 없을 때는 서서히 감속 // 입력이 없을 때는 서서히 감속
currentSpeed = Mathf.Lerp(currentSpeed, 0f, accelerationRate * Time.fixedDeltaTime); _currentSpeed = Mathf.Lerp(_currentSpeed, 0f, accelerationRate * Time.fixedDeltaTime);
_currentRotationSpeed = 0;
} }
ApplyDrag(); ApplyDrag();
ApplyMovement(); ApplyMovement();
@ -117,20 +112,17 @@ public class VoyagePlayerShipMovement : MonoBehaviour
ApplyMeshOffset(); ApplyMeshOffset();
#if UNITY_EDITOR #if UNITY_EDITOR
if (showDebugLines) UpdateDebugVisuals();
{
UpdateAllDebugLines();
}
#endif #endif
} }
private void HandleMovement() 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); float angleDifference = Vector3.Angle(transform.forward, inputDirection);
// 각도에 따른 속도 페널티 계산 (각도가 클수록 더 큰 감속) // 각도에 따른 속도 페널티 계산 (각도가 클수록 더 큰 감속)
@ -138,37 +130,38 @@ public class VoyagePlayerShipMovement : MonoBehaviour
turnPenaltyFactor = Mathf.Clamp01(turnPenaltyFactor); 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() 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); Quaternion targetRotation = Quaternion.LookRotation(inputDirection, Vector3.up);
// 회전 속도를 현재 속도에 비례하도록 설정 // 회전 속도를 현재 속도에 비례하도록 설정
float currentRotationSpeed = rotationSpeed * (currentSpeed / maxSpeed); float desiredRotationSpeed = rotationSpeed * (_currentSpeed / maxSpeed);
currentRotationSpeed = Mathf.Max(currentRotationSpeed, rotationSpeed * 0.3f); desiredRotationSpeed = Mathf.Max(desiredRotationSpeed, minRotationSpeed);
_currentRotationSpeed = Mathf.Lerp(_currentRotationSpeed, desiredRotationSpeed, rotationAccelerationRate * Time.fixedDeltaTime);
// 기본 회전 적용 (오브젝트 전체) // 기본 회전 적용 (오브젝트 전체)
transform.rotation = Quaternion.RotateTowards( transform.rotation = Quaternion.RotateTowards(
transform.rotation, transform.rotation,
targetRotation, targetRotation,
currentRotationSpeed * Time.fixedDeltaTime _currentRotationSpeed * Time.fixedDeltaTime
); );
} }
} }
@ -203,7 +196,7 @@ public class VoyagePlayerShipMovement : MonoBehaviour
private void UpdateAccelerationTilt() private void UpdateAccelerationTilt()
{ {
// 가속도 계산 // 가속도 계산
float acceleration = (currentSpeed - _prevSpeed) / Time.fixedDeltaTime; float acceleration = (_currentSpeed - _prevSpeed) / Time.fixedDeltaTime;
// 스프링 물리 시스템 구현 // 스프링 물리 시스템 구현
float springForce = -springStiffness * _currentAccelTilt; // 복원력 float springForce = -springStiffness * _currentAccelTilt; // 복원력
@ -225,7 +218,7 @@ public class VoyagePlayerShipMovement : MonoBehaviour
_currentAccelTilt = Mathf.Lerp(_currentAccelTilt, _currentAccelTilt + _accelTiltVelocity, accelTiltSpeed * Time.fixedDeltaTime); _currentAccelTilt = Mathf.Lerp(_currentAccelTilt, _currentAccelTilt + _accelTiltVelocity, accelTiltSpeed * Time.fixedDeltaTime);
_currentAccelTilt = Mathf.Clamp(_currentAccelTilt, -maxAccelTiltAngle, maxAccelTiltAngle); _currentAccelTilt = Mathf.Clamp(_currentAccelTilt, -maxAccelTiltAngle, maxAccelTiltAngle);
_prevSpeed = currentSpeed; _prevSpeed = _currentSpeed;
} }
private void ApplyMeshTilt() private void ApplyMeshTilt()
@ -246,108 +239,48 @@ public class VoyagePlayerShipMovement : MonoBehaviour
if (_meshTransform is null) return; if (_meshTransform is null) return;
// 현재 속도에 비례하여 파도 주기 조절 // 현재 속도에 비례하여 파도 주기 조절
float waveSpeedFactor = 1f + (currentSpeed / waveUnitSpeed) * speedWaveMultiplier; float waveSpeedFactor = 1f + (_currentSpeed / waveUnitSpeed) * speedWaveMultiplier;
_waveTime += Time.fixedDeltaTime * baseWaveFrequency * waveSpeedFactor; _waveTime += Time.fixedDeltaTime * baseWaveFrequency * waveSpeedFactor;
float currentSpeedByUnit = currentSpeed / waveUnitSpeed; float currentSpeedByUnit = _currentSpeed / waveUnitSpeed;
currentSpeedByUnit = Mathf.Clamp01(currentSpeedByUnit); currentSpeedByUnit = Mathf.Clamp01(currentSpeedByUnit);
float waveHeight = Mathf.Lerp(minSpeedWaveHeight, maxSpeedWaveHeight, currentSpeedByUnit); float waveHeight = Mathf.Lerp(minSpeedWaveHeight, maxSpeedWaveHeight, currentSpeedByUnit);
currentWaveHeight = waveHeight * Mathf.Sin(_waveTime + _waveRandomOffset); _currentWaveHeight = waveHeight * Mathf.Sin(_waveTime + _waveRandomOffset);
} }
private void ApplyMeshOffset() private void ApplyMeshOffset()
{ {
if (_meshTransform is null) return; if (_meshTransform is null) return;
Vector3 position = _originalMeshPosition + (Vector3.up * currentWaveHeight); Vector3 position = _originalMeshPosition + (Vector3.up * _currentWaveHeight);
_meshTransform.localPosition = position; _meshTransform.localPosition = position;
} }
private void ApplyDrag() 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() private void ApplyMovement()
{ {
transform.position += currentVelocity * Time.fixedDeltaTime; transform.position += _currentVelocity * Time.fixedDeltaTime;
} }
public void OnMove(InputAction.CallbackContext context) public void OnMove(InputAction.CallbackContext context)
{ {
currentInput = context.ReadValue<Vector2>(); _currentInput = context.ReadValue<Vector2>();
} }
#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<LineRenderer>();
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() private void OnValidate()
{ {
// 에디터에서 메시 오브젝트 이름이 변경될 때 자동으로 찾기 // 에디터에서 메시 오브젝트 이름이 변경될 때 자동으로 찾기
@ -356,4 +289,188 @@ public class VoyagePlayerShipMovement : MonoBehaviour
_meshTransform = transform.Find(meshObjectName); _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<LineRenderer>();
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
} }