DDD-43 코드 리팩토링

This commit is contained in:
Jeonghyeon Ha 2025-07-15 20:10:46 +09:00
parent 4a06cc0565
commit ef384bf59c
3 changed files with 342 additions and 241 deletions

View File

@ -14,6 +14,7 @@ GameObject:
- component: {fileID: -1082383067592254908} - component: {fileID: -1082383067592254908}
- component: {fileID: 7722456790212551628} - component: {fileID: 7722456790212551628}
- component: {fileID: 3140672700990605547} - component: {fileID: 3140672700990605547}
- component: {fileID: 66612183539046142}
m_Layer: 0 m_Layer: 0
m_Name: PlayerShip m_Name: PlayerShip
m_TagString: Untagged m_TagString: Untagged
@ -107,13 +108,15 @@ MonoBehaviour:
m_Script: {fileID: 11500000, guid: 2607481b15fd548b18ca4897db56ab3f, type: 3} m_Script: {fileID: 11500000, guid: 2607481b15fd548b18ca4897db56ab3f, type: 3}
m_Name: m_Name:
m_EditorClassIdentifier: m_EditorClassIdentifier:
movementSettings:
maxSpeed: 20 maxSpeed: 20
accelerationRate: 1 accelerationRate: 1
dragFactor: 0.98 dragFactor: 0.98
minSpeedThreshold: 0.1 minSpeedThreshold: 0.1
rotationSpeed: 270 rotationSettings:
maxRotationSpeed: 270
minRotationSpeed: 90 minRotationSpeed: 90
rotationAccelerationRate: 5 accelerationRate: 5
turnSpeedPenalty: 0.5 turnSpeedPenalty: 0.5
maxTurnAngle: 180 maxTurnAngle: 180
--- !u!114 &7722456790212551628 --- !u!114 &7722456790212551628
@ -157,9 +160,43 @@ MonoBehaviour:
m_Script: {fileID: 11500000, guid: 3d5c5f51b32b4633b887d096554c6cd9, type: 3} m_Script: {fileID: 11500000, guid: 3d5c5f51b32b4633b887d096554c6cd9, type: 3}
m_Name: m_Name:
m_EditorClassIdentifier: m_EditorClassIdentifier:
settings:
showDebugVisuals: 1 showDebugVisuals: 1
debugLineLength: 5 lineLength: 5
debugLineWidth: 0.1 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 --- !u!1 &6407855916708530114
GameObject: GameObject:
m_ObjectHideFlags: 0 m_ObjectHideFlags: 0

View File

@ -2,178 +2,208 @@ using UnityEngine;
using UnityEngine.InputSystem; using UnityEngine.InputSystem;
/// <summary> /// <summary>
/// 플레이어 배의 움직임을 제어하는 컴포넌트 /// 플레이어 배의 기본 이동과 회전을 처리하는 컴포넌트
/// 속도, 회전, 틸트, 파도 효과 등을 관리합니다.
/// </summary> /// </summary>
[RequireComponent(typeof(Rigidbody))]
public class VoyagePlayerShipMovement : MonoBehaviour public class VoyagePlayerShipMovement : MonoBehaviour
{ {
#region Inspector Fields #region Settings
[System.Serializable]
[Header("기본 이동 설정")] public class MovementSettings
{
[Tooltip("배의 최대 이동 속도")] [Tooltip("배의 최대 이동 속도")]
[SerializeField] private float maxSpeed = 20f; public float maxSpeed = 20f;
[SerializeField] private float accelerationRate = 1f; public float accelerationRate = 1f;
[SerializeField] private float dragFactor = 0.98f; public float dragFactor = 0.98f;
[SerializeField] private float minSpeedThreshold = 0.1f; public float minSpeedThreshold = 0.1f;
}
[Header("회전 설정")] [System.Serializable]
[SerializeField] private float rotationSpeed = 270f; public class RotationSettings
[SerializeField] private float minRotationSpeed = 90f; {
[SerializeField] private float rotationAccelerationRate = 5f; public float maxRotationSpeed = 270f;
[SerializeField] private float turnSpeedPenalty = 0.5f; public float minRotationSpeed = 90f;
[SerializeField] private float maxTurnAngle = 180f; public float accelerationRate = 5f;
[Tooltip("선회 시 감속 정도 (0: 감속 없음, 1: 완전 정지)")]
public float turnSpeedPenalty = 0.5f;
[Tooltip("최대 감속이 적용되는 각도")]
public float maxTurnAngle = 180f;
}
#endregion
#region Inspector Fields
[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 #endregion
#region Private Fields #region Private Fields
private Vector3 currentVelocity; private Vector3 currentVelocity;
private Vector2 currentInput; private Vector2 currentInput;
public Vector2 CurrentInput => currentInput;
private float currentRotationSpeed; private float currentRotationSpeed;
public float CurrentRotationSpeed => currentRotationSpeed;
private float targetSpeed; private float targetSpeed;
private float currentSpeed; 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 #endregion
#region Unity Messages #region Unity Messages
private void FixedUpdate() private void FixedUpdate()
{ {
UpdateMovement(); UpdateShipMovement();
}
#endregion
#region Public Methods
public void OnMove(InputAction.CallbackContext context)
{
currentInput = context.ReadValue<Vector2>();
} }
#endregion #endregion
#region Movement Methods #region Movement Methods
private void UpdateMovement() private void UpdateShipMovement()
{ {
if (IsMoving()) if (IsMoving())
{ {
HandleMovement(); UpdateMovementWithInput();
HandleRotation();
} }
else else
{ {
DecelerateMovement(); DecelerateShip();
} }
ApplyDrag(); ApplyDragForce();
ApplyMovement(); ApplyFinalMovement();
} }
private bool IsMoving() private void UpdateMovementWithInput()
{ {
return currentInput.magnitude > minSpeedThreshold; UpdateSpeed();
UpdateRotation();
} }
private void HandleMovement() private void UpdateSpeed()
{ {
float baseTargetSpeed = CalculateBaseTargetSpeed(); float baseTargetSpeed = CalculateBaseTargetSpeed();
float turnPenaltyFactor = CalculateTurnPenaltyFactor(); float turnPenaltyFactor = CalculateTurnPenaltyFactor();
targetSpeed = baseTargetSpeed * turnPenaltyFactor; targetSpeed = baseTargetSpeed * turnPenaltyFactor;
currentSpeed = Mathf.Lerp(currentSpeed, targetSpeed, accelerationRate * Time.fixedDeltaTime); currentSpeed = Mathf.Lerp(currentSpeed, targetSpeed,
movementSettings.accelerationRate * Time.fixedDeltaTime);
if (ShouldStop()) if (ShouldStop())
{ {
currentSpeed = 0f; StopShip();
} }
UpdateVelocityVector(); UpdateVelocityVector();
} }
private void HandleRotation() private void UpdateRotation()
{ {
if (IsMoving()) if (!IsMoving()) return;
{
Vector3 inputDirection = new Vector3(currentInput.x, 0, currentInput.y).normalized;
Quaternion targetRotation = Quaternion.LookRotation(inputDirection, Vector3.up);
// 회전 속도를 현재 속도에 비례하도록 설정 Quaternion targetRotation = CalculateTargetRotation();
float desiredRotationSpeed = rotationSpeed * (currentSpeed / maxSpeed); float rotationSpeed = CalculateRotationSpeed();
desiredRotationSpeed = Mathf.Max(desiredRotationSpeed, minRotationSpeed);
currentRotationSpeed = Mathf.Lerp(currentRotationSpeed, desiredRotationSpeed,
rotationAccelerationRate * Time.fixedDeltaTime);
// 기본 회전 적용 (오브젝트 전체) ApplyRotation(targetRotation, rotationSpeed);
transform.rotation = Quaternion.RotateTowards(
transform.rotation,
targetRotation,
currentRotationSpeed * Time.fixedDeltaTime
);
} }
#endregion
#region Helper Methods
private bool IsMoving()
{
return currentInput.magnitude > movementSettings.minSpeedThreshold;
} }
private float CalculateBaseTargetSpeed() private float CalculateBaseTargetSpeed()
{ {
return Mathf.Clamp01(currentInput.magnitude) * maxSpeed; return Mathf.Clamp01(currentInput.magnitude) * movementSettings.maxSpeed;
} }
private float CalculateTurnPenaltyFactor() private float CalculateTurnPenaltyFactor()
{ {
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);
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() 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() private void UpdateVelocityVector()
{ {
currentVelocity = transform.forward * currentSpeed; currentVelocity = transform.forward * currentSpeed;
} }
#endregion
private void ApplyDrag() private void DecelerateShip()
{ {
currentSpeed *= dragFactor; currentSpeed = Mathf.Lerp(currentSpeed, 0f,
movementSettings.accelerationRate * Time.fixedDeltaTime);
// 최소 속도 이하면 완전히 정지 currentRotationSpeed = 0f;
if (currentSpeed < minSpeedThreshold)
{
currentSpeed = 0f;
} }
// 현재 방향으로 감속된 속도 적용 private void ApplyDragForce()
currentVelocity = transform.forward * currentSpeed; {
currentSpeed *= movementSettings.dragFactor;
if (currentSpeed < movementSettings.minSpeedThreshold)
{
StopShip();
}
else
{
UpdateVelocityVector();
}
} }
private void ApplyMovement() private void ApplyFinalMovement()
{ {
transform.position += currentVelocity * Time.fixedDeltaTime; 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<Vector2>();
}
#endregion #endregion
} }

View File

@ -3,176 +3,180 @@ using UnityEngine;
namespace Voyage namespace Voyage
{ {
#if UNITY_EDITOR #if UNITY_EDITOR
using UnityEngine; /// <summary>
/// 배의 움직임을 시각적으로 디버깅하기 위한 컴포넌트
[RequireComponent(typeof(VoyagePlayerShipMovement)), RequireComponent(typeof(VoyagePlayerShipMovementVisual))] /// </summary>
[RequireComponent(typeof(VoyagePlayerShipMovement))]
[RequireComponent(typeof(VoyagePlayerShipMovementVisual))]
public class VoyagePlayerShipDebug : MonoBehaviour public class VoyagePlayerShipDebug : MonoBehaviour
{ {
[Header("Debug Visualization")] #region Debug Settings
[SerializeField] private bool showDebugVisuals = true; [System.Serializable]
[SerializeField] private float debugLineLength = 5f; public class DebugSettings
[SerializeField] private float debugLineWidth = 0.1f; {
public bool showDebugVisuals = true;
public float lineLength = 5f;
public float lineWidth = 0.1f;
private LineRenderer _speedLineRenderer; [Header("라인 색상")]
private LineRenderer _rotationSpeedLineRenderer; public Color speedLineColor = Color.green;
private LineRenderer _rotationDeltaLineRenderer; public Color rotationSpeedLineColor = Color.magenta;
private LineRenderer _TiltLineRenderer; public Color rotationDeltaLineColor = Color.yellow;
private LineRenderer _waveHeightLineRenderer; public Color tiltLineColor = Color.red;
private LineRenderer _wavePatternLineRenderer; 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 VoyagePlayerShipMovement movement;
private VoyagePlayerShipMovementVisual movementVisual; private VoyagePlayerShipMovementVisual movementVisual;
#endregion
#region Unity Messages
private void Start() private void Start()
{ {
if (!showDebugVisuals) return; if (!settings.showDebugVisuals) return;
movement = GetComponent<VoyagePlayerShipMovement>(); InitializeComponents();
movementVisual = GetComponent<VoyagePlayerShipMovementVisual>(); InitializeDebugLines();
InitializeDebugVisuals();
} }
private void Update() private void Update()
{ {
if (!showDebugVisuals) return; if (!settings.showDebugVisuals) return;
UpdateDebugVisuals(); UpdateAllDebugLines();
}
#endregion
#region Initialization
private void InitializeComponents()
{
movement = GetComponent<VoyagePlayerShipMovement>();
movementVisual = GetComponent<VoyagePlayerShipMovementVisual>();
} }
private void InitializeDebugVisuals() private void InitializeDebugLines()
{ {
if (!showDebugVisuals) return; lines.Speed = CreateLineRenderer("SpeedLine", settings.speedLineColor);
lines.RotationSpeed = CreateLineRenderer("RotationSpeedLine", settings.rotationSpeedLineColor);
// 속도 표시 lines.RotationDelta = CreateLineRenderer("RotationDeltaLine", settings.rotationDeltaLineColor);
_speedLineRenderer = CreateLineRenderer("SpeedLine", Color.green); lines.Tilt = CreateLineRenderer("TiltLine", settings.tiltLineColor);
// 회전 방향 표시 lines.WaveHeight = CreateLineRenderer("WaveHeightLine", settings.waveHeightLineColor);
_rotationSpeedLineRenderer = CreateLineRenderer("RotationSpeedLine", Color.magenta); lines.WavePattern = CreateLineRenderer("WavePatternLine", settings.wavePatternLineColor, 50);
// 회전 방향 표시
_rotationDeltaLineRenderer = CreateLineRenderer("RotationDeltaLine", Color.yellow);
// 틸트 표시
_TiltLineRenderer = CreateLineRenderer("TiltLine", Color.red);
// 파도 높이 표시
_waveHeightLineRenderer = CreateLineRenderer("WaveHeightLine", Color.blue);
// 파도 패턴 표시
_wavePatternLineRenderer = CreateLineRenderer("WavePatternLine", Color.cyan);
_wavePatternLineRenderer.positionCount = 50; // 파도 패턴을 위한 더 많은 점
} }
#endregion
private void UpdateDebugVisuals() #region Line Updates
private void UpdateAllDebugLines()
{ {
if (!showDebugVisuals) return;
// 속도 벡터 표시
UpdateSpeedLine(); UpdateSpeedLine();
UpdateRotationLines();
// 회전 방향 및 각속도 표시
UpdateRotationSpeedLine();
UpdateRotationDeltaLine();
// 회전 틸트 표시
UpdateTiltLine(); UpdateTiltLine();
// 파도 높이와 패턴 표시
UpdateWaveVisualization(); UpdateWaveVisualization();
} }
private float GetCurrentSpeed() => movement.CurrentSpeed;
private float GetMaxSpeed() => movement.MaxSpeed;
private float GetRotationSpeed() => movement.CurrentRotationSpeed;
private Vector2 GetCurrentInput() => movement.CurrentInput;
private void UpdateSpeedLine() private void UpdateSpeedLine()
{ {
Vector3 start = transform.position + Vector3.up * 1.5f; Vector3 start = GetDebugLineStart(1.5f);
Vector3 end = start + transform.forward * ((GetCurrentSpeed() / GetMaxSpeed()) * debugLineLength * 2); Vector3 direction = transform.forward * (movement.CurrentSpeed / movement.MaxSpeed);
DrawLine(_speedLineRenderer, start, end); 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; UpdateRotationSpeedArc();
// 각속도를 호로 표현 UpdateRotationDeltaArc();
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; private void UpdateRotationSpeedArc()
_rotationSpeedLineRenderer.SetPositions(arcPoints);
}
else
{ {
_rotationSpeedLineRenderer.positionCount = 0; if (Mathf.Abs(movement.CurrentRotationSpeed) <= 0.1f)
} {
lines.RotationSpeed.positionCount = 0;
return;
} }
private void UpdateRotationDeltaLine() DrawArc(lines.RotationSpeed,
{ GetDebugLineStart(1.2f),
float deltaAngle = 0f; settings.lineLength,
if (GetCurrentInput().magnitude > 0.1f) movement.CurrentRotationSpeed);
{
Vector3 inputDirection = new Vector3(GetCurrentInput().x, 0, GetCurrentInput().y).normalized;
Quaternion targetRotation = Quaternion.LookRotation(inputDirection, Vector3.up);
deltaAngle = Quaternion.Angle(transform.rotation, targetRotation);
} }
Vector3 start = transform.position + Vector3.up * 1.2f; private void UpdateRotationDeltaArc()
// 각속도를 호로 표현
if (Mathf.Abs(deltaAngle) > 0.1f)
{ {
Vector3[] arcPoints = new Vector3[10]; if (movement.CurrentInput.magnitude <= 0.1f)
float radius = debugLineLength * 1.05f;
float angleStep = deltaAngle * 1f / (arcPoints.Length - 1);
for (int i = 0; i < arcPoints.Length; i++)
{ {
float angle = angleStep * i; lines.RotationDelta.positionCount = 0;
Vector3 point = start + Quaternion.Euler(0, angle, 0) * transform.forward * radius; return;
arcPoints[i] = point;
} }
_rotationDeltaLineRenderer.positionCount = arcPoints.Length; float deltaAngle = CalculateRotationDeltaAngle();
_rotationDeltaLineRenderer.SetPositions(arcPoints); if (Mathf.Abs(deltaAngle) <= 0.1f)
}
else
{ {
_rotationDeltaLineRenderer.positionCount = 0; lines.RotationDelta.positionCount = 0;
return;
} }
DrawArc(lines.RotationDelta,
GetDebugLineStart(1.2f),
settings.lineLength * 1.05f,
deltaAngle);
} }
private void UpdateTiltLine() private void UpdateTiltLine()
{ {
Vector3 start = transform.position + Vector3.up * 1.5f; Vector3 start = GetDebugLineStart(1.5f);
Vector3 tiltDirection = movementVisual.MeshTransform.up; 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() private void UpdateWaveVisualization()
{
UpdateWaveHeightLine();
UpdateWavePatternLine();
}
private void UpdateWaveHeightLine()
{ {
// 현재 파도 높이 표시 // 현재 파도 높이 표시
Vector3 waveStart = transform.position + Vector3.up * 1.5f - transform.forward * 1.5f; Vector3 waveStart = transform.position + Vector3.up * 1.5f - transform.forward * 1.5f;
Vector3 waveEnd = waveStart + Vector3.up * (GetCurrentWaveHeight() * debugLineLength); Vector3 waveEnd = waveStart + Vector3.up * (movementVisual.CurrentWaveHeight * settings.lineLength);
DrawLine(_waveHeightLineRenderer, waveStart, waveEnd); DrawLine(lines.WaveHeight, waveStart, waveEnd);
}
private void UpdateWavePatternLine()
{
// 파도 패턴 시각화 // 파도 패턴 시각화
Vector3[] wavePoints = new Vector3[_wavePatternLineRenderer.positionCount]; Vector3[] wavePoints = new Vector3[lines.WavePattern.positionCount];
float waveLength = debugLineLength * 2f; float waveLength = settings.lineLength * 2f;
for (int i = 0; i < wavePoints.Length; i++) 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 x = t * waveLength - waveLength * 0.5f;
float currentSpeedByUnit = GetCurrentSpeed() / GetWaveUnitSpeed(); float currentSpeedByUnit = movement.CurrentSpeed / movementVisual.WaveUnitSpeed;
currentSpeedByUnit = Mathf.Clamp01(currentSpeedByUnit); currentSpeedByUnit = Mathf.Clamp01(currentSpeedByUnit);
float waveHeight = Mathf.Lerp(GetMinSpeedWaveHeight(), GetMaxSpeedWaveHeight(), currentSpeedByUnit); float waveHeight = Mathf.Lerp(movementVisual.MinSpeedWaveHeight, movementVisual.MaxSpeedWaveHeight, currentSpeedByUnit);
float y = Mathf.Sin((GetWaveTime() + x) * GetBaseWaveFrequency()) * waveHeight; float y = Mathf.Sin((movementVisual.WaveTime + x) * movementVisual.BaseWaveFrequency) * waveHeight;
wavePoints[i] = transform.position + wavePoints[i] = transform.position +
Vector3.right * x + Vector3.right * x +
@ -180,43 +184,73 @@ namespace Voyage
wavePoints[i] += Vector3.back * 3f + Vector3.down * 1f; 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 CalculateRotationDeltaAngle()
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)
{ {
GameObject lineObj = new GameObject(name); Vector3 inputDirection = new Vector3(movement.CurrentInput.x, 0, movement.CurrentInput.y).normalized;
lineObj.transform.SetParent(transform); Quaternion targetRotation = Quaternion.LookRotation(inputDirection, Vector3.up);
LineRenderer line = lineObj.AddComponent<LineRenderer>(); return Quaternion.Angle(transform.rotation, targetRotation);
}
line.startWidth = debugLineWidth; private void DrawArc(LineRenderer lineRenderer, Vector3 center, float radius, float totalAngle)
line.endWidth = debugLineWidth; {
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<LineRenderer>();
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.material = new Material(Shader.Find("Universal Render Pipeline/Unlit"));
line.startColor = color; line.startColor = line.endColor = color;
line.endColor = color; line.positionCount = pointCount;
line.positionCount = 2;
line.shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.Off; line.shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.Off;
line.receiveShadows = false; line.receiveShadows = false;
line.material.color = color; line.material.color = color;
return line;
} }
private void DrawLine(LineRenderer line, Vector3 start, Vector3 end) private void DrawLine(LineRenderer line, Vector3 start, Vector3 end)
{ {
if (line is null) return; if (line is null) return;
line.positionCount = 2; line.positionCount = 2;
line.SetPosition(0, start); line.SetPosition(0, start);
line.SetPosition(1, end); line.SetPosition(1, end);
} }
#endregion
} }
#endif #endif
} }