이동 및 점프 (3D)

PTK·2024년 12월 25일
0

유니티에서 이동 및 점프하는 법 (FPS 게임)

3D

Rigidbody _rb; // 플레이어의 Rigidbody 컴포넌트

[Header("플레이어 움직임")]
[SerializeField] float _moveSpeed = 3f; // 기본 이동 속도
[SerializeField] float _rotateSpeed = 300f; // 회전 속도
[SerializeField] float _jumpForce = 10; // 점프 시 적용되는 힘
[SerializeField] float _mouseSensitivity = 1f; // 마우스 민감도
float _run; // 달리기 속도

[Header("플레이어 카메라")]
[SerializeField] Vector3 _offset; // 카메라와 플레이어 간 거리 오프셋
[SerializeField] Camera _mainCamera; // 플레이어의 메인 카메라
[SerializeField] float _yRotationRange = 60f; // 카메라의 상하 회전 제한 각도
[SerializeField] float _yRotation = 0f; // 카메라의 현재 상하 회전 각도

[SerializeField] bool _isJumped; // 플레이어가 점프 중인지 확인하는 변수

private void Start()
{
    _rb = gameObject.GetComponent<Rigidbody>();

    _isJumped = false; // 초기 점프 상태 설정

    _run = _moveSpeed * 2; // 달리기 속도를 기본 이동 속도의 두 배로 설정

    // 커서 숨기기 및 잠금
    Cursor.visible = false;
    Cursor.lockState = CursorLockMode.Locked;
}

private void Update()
{
    // 왼쪽 Shift 키를 눌러 달리기, 떼면 기본 속도로 복구
    if (Input.GetKeyDown(KeyCode.LeftShift) || Input.GetKeyUp(KeyCode.LeftShift))
    {
        _moveSpeed = Input.GetKey(KeyCode.LeftShift) ? _run : _run / 2;
    }

    Jump();
    Move();
    Fire();
}

private void Fire()
{
    if (Input.GetMouseButtonDown(0))
    {
        Debug.Log("Fire");
    }
}

private void Jump()
{
    if (Input.GetKeyDown(KeyCode.Space) && !_isJumped)
    {
        _isJumped = true; // 점프 상태로 변경
        _rb.AddForce(Vector3.up * _jumpForce, ForceMode.Impulse); // 위로 힘을 가해 점프
    }
}

private void OnCollisionEnter(Collision collision)
{
    if (collision.gameObject.CompareTag("Floor"))
    {
        _isJumped = false;
    }
}

private void Move()
{
    // 마우스 입력값 가져오기
    Vector2 rotateInput = new(Input.GetAxis("Mouse X"), Input.GetAxis("Mouse Y"));
    SetRotation(rotateInput); // 플레이어와 카메라 회전 처리

    // 키보드 입력값 가져오기
    Vector3 moveInput = new(Input.GetAxis("Horizontal"), 0, Input.GetAxis("Vertical"));
    SetPosition(moveInput); // 플레이어 이동 처리
}

private void SetRotation(Vector2 input)
{
    // 마우스 X 입력으로 플레이어 좌우 회전
    if (input.x != 0)
    {
        transform.Rotate(Vector3.up, input.x * _rotateSpeed * _mouseSensitivity * Time.deltaTime);
    }

    // 마우스 Y 입력으로 카메라 상하 회전
    if (input.y != 0)
    {
        _yRotation = _yRotation + -input.y * _rotateSpeed * _mouseSensitivity * Time.deltaTime; // 상하 회전 계산
        _yRotation = Mathf.Clamp(_yRotation, -_yRotationRange, _yRotationRange); // 회전 각도를 제한

        _mainCamera.transform.localRotation = Quaternion.Euler(_yRotation, 0f, 0f); // 카메라 회전 적용
    }
}

private void SetPosition(Vector3 input)
{
    // 입력값으로 이동 방향 계산
    Vector3 moveDirection = transform.forward * input.z + transform.right * input.x;
    moveDirection.Normalize(); // 방향 벡터 정규화
    Vector3 velocity = moveDirection * _moveSpeed; // 이동 속도 계산

    // 부드러운 이동을 위해 속도 보간 처리
    _rb.velocity = Vector3.Lerp(_rb.velocity, new Vector3(velocity.x, _rb.velocity.y, velocity.z), 0.1f);
}

위 코드에서 사용된 CameraController 스크립트 (카메라 컴포턴트)

CameraController

private bool _hasFollowTarget; // FollowTarget이 설정되었는지 여부를 나타내는 플래그
private Transform _followTarget; // 카메라가 따라가야 할 타겟 오브젝트

// FollowTarget 프로퍼티: 타겟 설정 시 플래그 업데이트
public Transform FollowTarget
{
    get => _followTarget; // 타겟 반환
    set
    {
        _followTarget = value; // 새로운 타겟 설정
        _hasFollowTarget = _followTarget != null; // 타겟이 null인지 여부로 플래그 설정
    }
}

private void LateUpdate()
{
    // 타겟이 설정된 경우에만 Transform 업데이트
    if (_hasFollowTarget)
    {
        SetTransform();
    }
}

// 카메라의 위치와 회전을 타겟에 맞게 동기화
private void SetTransform()
{
    _followTarget.SetPositionAndRotation(transform.position, transform.rotation);
}

깃허브 주소 https://github.com/zxllo12/FPS_Study.git

0개의 댓글