DDD-43 해상 배 조작 - 회전에 따른 틸팅
This commit is contained in:
parent
70702f3235
commit
2c026cae7b
@ -37,23 +37,28 @@ public class VoyagePlayerShipMovement : MonoBehaviour
|
||||
[Header("Tilt Settings")]
|
||||
[SerializeField] private float maxTiltAngle = 15f;
|
||||
[SerializeField] private float tiltSpeed = 5f;
|
||||
[SerializeField] private string meshObjectName = "Ship_Mesh"; // 메시 오브젝트의 이름
|
||||
private Transform meshTransform; // 메시 트랜스폼
|
||||
private float currentTilt = 0f;
|
||||
private Quaternion originalMeshRotation; // 메시의 초기 회전값 저장
|
||||
[SerializeField] private float returnSpeed = 3f; // 원래 자세로 돌아오는 속도
|
||||
[SerializeField] private float angularVelocityMultiplier = 2f; // 각속도 영향력
|
||||
[SerializeField] private string meshObjectName = "Ship_Mesh";
|
||||
|
||||
private Transform _meshTransform;
|
||||
private float _currentTilt = 0f;
|
||||
private Quaternion _originalMeshRotation;
|
||||
private float _lastRotationY; // 이전 프레임의 Y축 회전값
|
||||
private float _currentAngularVelocity; // 현재 각속도
|
||||
|
||||
private void Start()
|
||||
{
|
||||
// 하위 오브젝트에서 메시 찾기
|
||||
meshTransform = transform.Find(meshObjectName);
|
||||
if (meshTransform == null)
|
||||
_meshTransform = transform.Find(meshObjectName);
|
||||
if (_meshTransform == null)
|
||||
{
|
||||
Debug.LogError($"메시 오브젝트를 찾을 수 없습니다: {meshObjectName}");
|
||||
enabled = false;
|
||||
return;
|
||||
}
|
||||
|
||||
// 메시의 초기 회전값 저장
|
||||
originalMeshRotation = meshTransform.localRotation;
|
||||
_originalMeshRotation = _meshTransform.localRotation;
|
||||
_lastRotationY = transform.eulerAngles.y;
|
||||
}
|
||||
|
||||
private void FixedUpdate()
|
||||
@ -68,6 +73,7 @@ public class VoyagePlayerShipMovement : MonoBehaviour
|
||||
// 입력이 없을 때는 서서히 감속
|
||||
currentSpeed = Mathf.Lerp(currentSpeed, 0f, accelerationRate * Time.fixedDeltaTime);
|
||||
}
|
||||
UpdateMeshRotationTilt();
|
||||
|
||||
ApplyDrag();
|
||||
ApplyMovement();
|
||||
@ -121,38 +127,46 @@ public class VoyagePlayerShipMovement : MonoBehaviour
|
||||
float currentRotationSpeed = rotationSpeed * (currentSpeed / maxSpeed);
|
||||
currentRotationSpeed = Mathf.Max(currentRotationSpeed, rotationSpeed * 0.3f);
|
||||
|
||||
// 회전 방향에 따른 목표 기울기 계산
|
||||
float turnDirection = Vector3.SignedAngle(transform.forward, inputDirection, Vector3.up);
|
||||
float targetTilt = -Mathf.Sign(turnDirection) * maxTiltAngle * (currentSpeed / maxSpeed);
|
||||
|
||||
// 현재 기울기를 목표 기울기로 부드럽게 보간
|
||||
currentTilt = Mathf.Lerp(currentTilt, targetTilt, tiltSpeed * Time.fixedDeltaTime);
|
||||
|
||||
// 기본 회전 적용 (오브젝트 전체)
|
||||
transform.rotation = Quaternion.RotateTowards(
|
||||
transform.rotation,
|
||||
targetRotation,
|
||||
currentRotationSpeed * Time.fixedDeltaTime
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// 메시에만 z축 기울기 적용
|
||||
if (meshTransform != null)
|
||||
{
|
||||
meshTransform.localRotation = originalMeshRotation * Quaternion.Euler(0, 0, currentTilt);
|
||||
}
|
||||
private void UpdateMeshRotationTilt()
|
||||
{
|
||||
if (_meshTransform is null) return;
|
||||
|
||||
// 현재 Y축 회전값과 각속도 계산
|
||||
float currentRotationY = transform.eulerAngles.y;
|
||||
float deltaRotation = Mathf.DeltaAngle(_lastRotationY, currentRotationY);
|
||||
_currentAngularVelocity = deltaRotation / Time.fixedDeltaTime;
|
||||
|
||||
// 목표 틸트 각도 계산
|
||||
float targetTilt = -_currentAngularVelocity * angularVelocityMultiplier;
|
||||
targetTilt = Mathf.Clamp(targetTilt, -maxTiltAngle, maxTiltAngle);
|
||||
|
||||
// 틸트 적용 또는 복귀
|
||||
if (Mathf.Abs(_currentAngularVelocity) > 0.1f)
|
||||
{
|
||||
_currentTilt = Mathf.Lerp(_currentTilt, targetTilt, tiltSpeed * Time.fixedDeltaTime);
|
||||
}
|
||||
else
|
||||
{
|
||||
// 입력이 없을 때는 기울기를 서서히 0으로
|
||||
currentTilt = Mathf.Lerp(currentTilt, 0f, tiltSpeed * Time.fixedDeltaTime);
|
||||
|
||||
if (meshTransform != null)
|
||||
{
|
||||
meshTransform.localRotation = originalMeshRotation * Quaternion.Euler(0, 0, currentTilt);
|
||||
}
|
||||
// 입력이 없을 때는 원래 자세로 천천히 복귀
|
||||
_currentTilt = Mathf.Lerp(_currentTilt, 0f, returnSpeed * Time.fixedDeltaTime);
|
||||
}
|
||||
|
||||
// 메시에 틸트 적용
|
||||
_meshTransform.localRotation = _originalMeshRotation * Quaternion.Euler(0, 0, _currentTilt);
|
||||
|
||||
_lastRotationY = currentRotationY;
|
||||
}
|
||||
|
||||
|
||||
private void ApplyDrag()
|
||||
{
|
||||
currentSpeed *= dragFactor;
|
||||
@ -196,9 +210,9 @@ public class VoyagePlayerShipMovement : MonoBehaviour
|
||||
DrawDebugLine(forwardDirectionLine, transform.forward, debugLineLength, 0);
|
||||
|
||||
// 메시의 위쪽 방향 표시 (틸팅 반영)
|
||||
if (meshTransform is not null)
|
||||
if (_meshTransform is not null)
|
||||
{
|
||||
DrawDebugLine(upDirectionLine, meshTransform.up, debugLineLength, debugLineHeightStep);
|
||||
DrawDebugLine(upDirectionLine, _meshTransform.up, debugLineLength, debugLineHeightStep);
|
||||
}
|
||||
|
||||
// 입력 방향 표시 (두 단계 위)
|
||||
@ -245,7 +259,7 @@ public class VoyagePlayerShipMovement : MonoBehaviour
|
||||
// 에디터에서 메시 오브젝트 이름이 변경될 때 자동으로 찾기
|
||||
if (Application.isEditor && !Application.isPlaying)
|
||||
{
|
||||
meshTransform = transform.Find(meshObjectName);
|
||||
_meshTransform = transform.Find(meshObjectName);
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user