void Move()
{
// 입력된 y값을 z축(앞뒤), x값을 x축(좌우)에 반영하여 이동 방향 계산
Vector3 dir = transform.forward * curMovementInput.y + transform.right * curMovementInput.x;
// 이동 속도 적용
dir *= moveSpeed;
// y축 속도는 중력 영향을 받게 기존 Rigidbody y속도를 유지
dir.y = _rigidbody.velocity.y;
// 계산된 방향 벡터를 실제 물리 속도로 반영
_rigidbody.velocity = dir;
}
// InputAction.CallbackContext는 입력 이벤트에 대한 정보(값, 상태 등)를 담고 있음
public void OnMove(InputAction.CallbackContext context)
{
// context의 상태와 InputActionPhase.Performed(입력중)라는 enum 값을 비교
if (context.phase == InputActionPhase.Performed)
{
curMovementInput = context.ReadValue<Vector2>();
}
// context의 상태와 InputActionPhase.Canceled(입력되지않음)라는 enum 값을 비교
else if (context.phase == InputActionPhase.Canceled)
{
curMovementInput = Vector2.zero;
}
}
void CameraLook()
{
// 마우스의 Y 이동값에 감도를 곱해서 상하 회전 각도를 누적
camCurXRot += mouseDelta.y * lookSensitivity;
// camCurXRot 값이 너무 위나 아래로 꺾이지 않게 최소/최대값 제한
camCurXRot = Mathf.Clamp(camCurXRot, minXLook, maxXLook);
// 카메라 컨테이너의 회전을 camCurXRot만큼 적용 (상하 회전)
cameraContainer.localEulerAngles = new Vector3(-camCurXRot, 0, 0);
// 플레이어 오브젝트의 Y 회전에 마우스 X 이동값을 적용 (좌우 회전)
transform.eulerAngles += new Vector3(0, mouseDelta.x * lookSensitivity, 0);
}
public void OnLook(InputAction.CallbackContext context)
{
mouseDelta = context.ReadValue<Vector2>();
}
마우스를 Y축 이동은 X축 회전이므로 -camCurXRot를 적용해야 상하 카메라 회전이 된다
public void OnJump(InputAction.CallbackContext context)
{
// 입력이 시작될 때와 착지 상태일때
if (context.phase == InputActionPhase.Started && IsGrounded())
{
// 위쪽 방향으로 점프 힘을 가함 (Impulse로 순간적인 힘을 가함)
_rigidbody.AddForce(Vector2.up * jumpPower, ForceMode.Impulse);
}
}
bool IsGrounded()
{
// 플레이어의 네 방향에서 아래로 향하는 Ray를 약간위에서 생성해서 바닥과 닿는지 확인
Ray[] rays = new Ray[4]
{
new Ray(transform.position + (transform.forward * 0.2f) + (transform.up * 0.01f), Vector3.down),
new Ray(transform.position + (-transform.forward * 0.2f) + (transform.up * 0.01f), Vector3.down),
new Ray(transform.position + (transform.right * 0.2f) + (transform.up * 0.01f), Vector3.down),
new Ray(transform.position + (-transform.right * 0.2f) + (transform.up * 0.01f), Vector3.down),
};
// 생성한 네 개의 Ray 중 하나라도 바닥에 닿으면 true 반환
foreach (Ray ray in rays)
{
if (Physics.Raycast(ray, 0.1f, groundLayerMask))
return true;
}
// 네 개의 Ray 모두 닿지 않았으면 공중에 떠 있는 상태
return false;
}
3D 개발이다 보니 축이 하나 더 늘어나서, 2D로 학습하던 때보다 상대적으로 더 복잡하고 어려운 부분이 있는 것 같다. 특히 회전이나 방향 처리에서 X, Y, Z축 개념을 정확히 이해하지 않으면 헷갈리기 쉬웠다. 그래도 Raycast 같은 새로운 개념들을 배우면서, 3D에서만 할 수 있는 판정 방식이나 표현들이 신기하고 흥미롭게 느껴졌다.