DDD-43 이동 기본 구현
This commit is contained in:
parent
0d2a8a5e2c
commit
70702f3235
@ -105,6 +105,18 @@ MonoBehaviour:
|
||||
m_Script: {fileID: 11500000, guid: 2607481b15fd548b18ca4897db56ab3f, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
maxSpeed: 10
|
||||
rotationSpeed: 120
|
||||
accelerationRate: 2
|
||||
minSpeedThreshold: 0.1
|
||||
dragFactor: 0.98
|
||||
turnSpeedPenalty: 0.5
|
||||
maxTurnAngle: 180
|
||||
showDebugLines: 1
|
||||
debugLineLength: 4
|
||||
debugLineHeightStep: 0.1
|
||||
maxTiltAngle: 15
|
||||
tiltSpeed: 5
|
||||
--- !u!1 &6407855916708530114
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
@ -118,7 +130,7 @@ GameObject:
|
||||
- component: {fileID: 9176830315433650152}
|
||||
- component: {fileID: 8182957266188503550}
|
||||
m_Layer: 0
|
||||
m_Name: Sphere
|
||||
m_Name: Ship_Mesh
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
@ -134,8 +146,8 @@ Transform:
|
||||
serializedVersion: 2
|
||||
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
|
||||
m_LocalPosition: {x: 0, y: 0, z: 0}
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_ConstrainProportionsScale: 0
|
||||
m_LocalScale: {x: 2, y: 2, z: 2}
|
||||
m_ConstrainProportionsScale: 1
|
||||
m_Children: []
|
||||
m_Father: {fileID: 7177504742663284911}
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
|
@ -3,66 +3,249 @@ using UnityEngine.InputSystem;
|
||||
|
||||
public class VoyagePlayerShipMovement : MonoBehaviour
|
||||
{
|
||||
private void Start()
|
||||
{
|
||||
[Header("Movement Settings")]
|
||||
[SerializeField] private float maxSpeed = 10f;
|
||||
|
||||
[SerializeField] private float rotationSpeed = 120f;
|
||||
[SerializeField] private float accelerationRate = 2f;
|
||||
[SerializeField] private float minSpeedThreshold = 0.1f;
|
||||
[SerializeField] private float dragFactor = 0.98f;
|
||||
|
||||
[Header("Turn Settings")]
|
||||
[SerializeField] private float turnSpeedPenalty = 0.5f; // 선회 시 감속 정도 (0: 감속 없음, 1: 완전 정지)
|
||||
[SerializeField] private float maxTurnAngle = 180f; // 최대 감속이 적용되는 각도
|
||||
|
||||
|
||||
#if UNITY_EDITOR
|
||||
// 현재 방향을 표시할 LineRenderer 설정
|
||||
forwardDirectionLine = CreateLineRenderer("CurrentDirectionLine", Color.green);
|
||||
upDirectionLine = CreateLineRenderer("upDirectionLine", Color.yellow);
|
||||
// 입력 방향을 표시할 LineRenderer 설정
|
||||
inputDirectionLine = CreateLineRenderer("InputDirectionLine", Color.red);
|
||||
#endif
|
||||
}
|
||||
|
||||
public void OnMove(InputAction.CallbackContext context)
|
||||
{
|
||||
Vector2 inputVector = context.ReadValue<Vector2>();
|
||||
|
||||
Vector3 currentForward = transform.forward;
|
||||
Vector3 currentUp = transform.up;
|
||||
Vector3 inputDirection = new Vector3(inputVector.x, 0, inputVector.y).normalized;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#if UNITY_EDITOR
|
||||
DrawDebugLine(forwardDirectionLine, currentForward);
|
||||
DrawDebugLine(upDirectionLine, currentUp);
|
||||
DrawDebugLine(inputDirectionLine, inputDirection);
|
||||
#endif
|
||||
}
|
||||
|
||||
// Debug draw below...
|
||||
#if UNITY_EDITOR
|
||||
private LineRenderer inputDirectionLine;
|
||||
[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
|
||||
|
||||
private Vector3 currentVelocity;
|
||||
private Vector2 currentInput;
|
||||
private float targetSpeed;
|
||||
private float currentSpeed;
|
||||
|
||||
[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; // 메시의 초기 회전값 저장
|
||||
|
||||
private void Start()
|
||||
{
|
||||
// 하위 오브젝트에서 메시 찾기
|
||||
meshTransform = transform.Find(meshObjectName);
|
||||
if (meshTransform == null)
|
||||
{
|
||||
Debug.LogError($"메시 오브젝트를 찾을 수 없습니다: {meshObjectName}");
|
||||
return;
|
||||
}
|
||||
|
||||
// 메시의 초기 회전값 저장
|
||||
originalMeshRotation = meshTransform.localRotation;
|
||||
}
|
||||
|
||||
private void FixedUpdate()
|
||||
{
|
||||
if (currentInput.magnitude > minSpeedThreshold)
|
||||
{
|
||||
HandleMovement();
|
||||
HandleRotation();
|
||||
}
|
||||
else
|
||||
{
|
||||
// 입력이 없을 때는 서서히 감속
|
||||
currentSpeed = Mathf.Lerp(currentSpeed, 0f, accelerationRate * Time.fixedDeltaTime);
|
||||
}
|
||||
|
||||
ApplyDrag();
|
||||
ApplyMovement();
|
||||
|
||||
#if UNITY_EDITOR
|
||||
if (showDebugLines)
|
||||
{
|
||||
UpdateAllDebugLines();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
private void HandleMovement()
|
||||
{
|
||||
// 기본 목표 속도 계산 (입력 크기에 비례)
|
||||
float baseTargetSpeed = Mathf.Clamp01(currentInput.magnitude) * maxSpeed;
|
||||
|
||||
// 현재 방향과 목표 방향 사이의 각도 계산
|
||||
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)
|
||||
{
|
||||
currentSpeed = 0f;
|
||||
}
|
||||
|
||||
// 현재 바라보는 방향으로 속도 벡터 업데이트
|
||||
currentVelocity = transform.forward * currentSpeed;
|
||||
}
|
||||
|
||||
private void HandleRotation()
|
||||
{
|
||||
if (currentInput.magnitude > minSpeedThreshold)
|
||||
{
|
||||
Vector3 inputDirection = new Vector3(currentInput.x, 0, currentInput.y).normalized;
|
||||
Quaternion targetRotation = Quaternion.LookRotation(inputDirection, Vector3.up);
|
||||
|
||||
// 회전 속도를 현재 속도에 비례하도록 설정
|
||||
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);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// 입력이 없을 때는 기울기를 서서히 0으로
|
||||
currentTilt = Mathf.Lerp(currentTilt, 0f, tiltSpeed * Time.fixedDeltaTime);
|
||||
|
||||
if (meshTransform != null)
|
||||
{
|
||||
meshTransform.localRotation = originalMeshRotation * Quaternion.Euler(0, 0, currentTilt);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void ApplyDrag()
|
||||
{
|
||||
currentSpeed *= dragFactor;
|
||||
|
||||
// 최소 속도 이하면 완전히 정지
|
||||
if (currentSpeed < minSpeedThreshold)
|
||||
{
|
||||
currentSpeed = 0f;
|
||||
}
|
||||
|
||||
// 현재 방향으로 감속된 속도 적용
|
||||
currentVelocity = transform.forward * currentSpeed;
|
||||
}
|
||||
|
||||
|
||||
private void ApplyMovement()
|
||||
{
|
||||
transform.position += currentVelocity * Time.fixedDeltaTime;
|
||||
}
|
||||
|
||||
public void OnMove(InputAction.CallbackContext context)
|
||||
{
|
||||
currentInput = context.ReadValue<Vector2>();
|
||||
// Debug Log this
|
||||
Debug.Log(currentInput);
|
||||
}
|
||||
|
||||
#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>();
|
||||
|
||||
// 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)
|
||||
|
||||
private void DrawDebugLine(LineRenderer renderer, Vector3 direction, float length, float heightOffset)
|
||||
{
|
||||
const float lineLength = 4;
|
||||
Vector3 position = transform.position;
|
||||
// 현재 방향 라인 업데이트 (파란색)
|
||||
if (!renderer) return;
|
||||
|
||||
Vector3 position = transform.position + Vector3.up * heightOffset;
|
||||
renderer.SetPosition(0, position);
|
||||
renderer.SetPosition(1, position + direction * lineLength);
|
||||
renderer.SetPosition(1, position + direction * length);
|
||||
}
|
||||
#endif
|
||||
|
||||
private void OnValidate()
|
||||
{
|
||||
// 에디터에서 메시 오브젝트 이름이 변경될 때 자동으로 찾기
|
||||
if (Application.isEditor && !Application.isPlaying)
|
||||
{
|
||||
meshTransform = transform.Find(meshObjectName);
|
||||
}
|
||||
}
|
||||
}
|
@ -33,7 +33,7 @@ Material:
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _BaseMap:
|
||||
m_Texture: {fileID: 2800000, guid: 9fab180d66628484a9bf08ce8bbd51c8, type: 3}
|
||||
m_Texture: {fileID: 2800000, guid: b28a01dbcbf8f0c4c8b70e10b99d5a28, type: 3}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _BlendTex:
|
||||
|
Loading…
Reference in New Issue
Block a user