이동 및 점프 (2D)

PTK·2024년 12월 15일
0

유니티에서 이동 및 점프하는 법 (플랫포머 게임)

2D

[SerializeField] Rigidbody2D _rigid; // 오브젝트의 Rigidbody2D 컴포넌트를 인스펙터에서 연결

[SerializeField] float _movePower = 10f; // 이동 시 가할 힘의 크기

[SerializeField] float _jumpPower = 5f; // 점프 시 가할 힘의 크기

[SerializeField] float _maxMoveSpeed = 10f; // 최대 이동 속도

float _x; // 입력된 좌우 방향 값을 저장하는 변수

bool _isGrounded; // 지면에 닿아있는지를 확인하는 변수

bool _jumpRequested; // 점프 입력 여부를 나타내는 플래그 변수


private void Update()
{
    _x = Input.GetAxisRaw("Horizontal"); // 좌우 입력 값을 가져옴 (왼쪽: -1, 중립: 0, 오른쪽: 1)

     if (Input.GetKeyDown(KeyCode.Space) && _isGrounded)
     {
         _jumpRequested = true; // 점프 요청 플래그 활성화
     }
}

private void FixedUpdate()
{
    Move();

    if (_jumpRequested) // 점프 요청이 있을 경우
    {
        Jump();
        _jumpRequested = false; // 점프 요청 초기화
    }
}

private void Move()
{
    // 현재 속도가 최대 이동 속도보다 낮을 경우에만 이동 힘을 추가
    if (Mathf.Abs(_rigid.velocity.x) < _maxMoveSpeed)
    {
        _rigid.AddForce(Vector2.right * _x * _movePower, ForceMode2D.Force);
    }
}

private void Jump()
{
    _rigid.AddForce(Vector2.up * _jumpPower, ForceMode2D.Impulse);
}

private void OnCollisionEnter2D(Collision2D collision)
{
    // 충돌한 오브젝트의 태그가 "Ground"일 경우 지면에 닿았다고 판단
    if (collision.gameObject.CompareTag("Ground"))
    {
        _isGrounded = true;
    }
}

private void OnCollisionExit2D(Collision2D collision)
{
    // 충돌이 끝난 오브젝트의 태그가 "Ground"일 경우 지면에서 벗어났다고 판단
    if (collision.gameObject.CompareTag("Ground"))
    {
        _isGrounded = false;
    }
}

좌우 입력 값을 Input.GetAxisRaw로 받은 이유.

Input.GetAxisRaw 와 Input.GetAxis 의 차이점

Input.GetAxisRaw는 유니티에서 입력 장치(키보드, 조이스틱, 마우스 등)로부터 입력 값을 가져오는 함수다.

즉각적이고 간단한 디지털 입력 처리가 필요할 때 유용하다. (2D 플랫폼 게임처럼 빠른 반응이 중요한 게임)

FixedUpdate를 사용한 이유.

유니티에서 FixedUpdate를 사용하는 이유는 물리 연산과 관련된 작업을 정확하고 안정적으로 처리하기 위해서다.

주요 특징으로

  1. 고정된 호출 간격:
    FixedUpdate는 게임 프레임 속도와 관계없이 일정한 간격으로 호출된다.
    물리 엔진이 매 프레임이 아닌 고정된 시간 간격(기본 0.02초)에 따라 동작하므로, 물리 연산(예: 속도, 힘, 충돌 등)을 일관되게 처리한다.

  2. 물리 연산에 적합:
    유니티의 물리 시스템(예: Rigidbody, Collider 등)은 FixedUpdate에서 처리되도록 설계되었다.
    Rigidbody.AddForce와 같은 물리 연산은 FixedUpdate에서 호출해야 정상적으로 동작하며, 부정확한 결과를 방지할 수 있다.

  3. Time.deltaTime과 차이점:
    FixedUpdate는 Time.fixedDeltaTime(고정 시간 간격)을 사용한다.
    Update에서의 Time.deltaTime은 프레임마다 변할 수 있지만, FixedUpdate에서는 항상 일정한 값을 갖는다.

이동 및 점프를 Update에 코딩하면 컴퓨터의 성능에 따라서 적용되는 속도가 다를 수 있다.

Mathf.Abs를 사용한 이유.

Mathf.Abs는 유니티의 Mathf 클래스에서 제공하는 함수로, 주어진 숫자의 절대값(Absolute Value)을 반환한다.

절대값은 숫자의 부호를 제거한 값으로, 양수와 음수 모두 0 또는 양수로 변환된다.

즉, 음수는 양수로, 양수는 그대로 반환된다.

사용하는 이유로

  1. 부호와 관계없이 값을 비교하거나 처리해야 할 때.

  2. 음수 값으로 인한 오류를 방지:
    예를 들어, 거리나 속도처럼 항상 양수로 표현되어야 하는 값.

  3. 다양한 수학적/게임 로직에서 필수적:
    충돌 거리 계산, 속도 제한, 점수 차 계산 등.

Rigidbody.AddForce를 사용한 이유.

유니티의 Rigidbody.AddForce 메서드는 Rigidbody에 특정 방향과 크기의 힘(Force)을 가하여 물체를 움직이는 데 사용된다.

2D 물리에서는 Rigidbody2D.AddForce로 동일하게 동작한다.

매개변수

  1. force (필수):
    힘의 방향과 크기를 나타내는 벡터.
    벡터 크기(Magnitude)는 힘의 세기를, 벡터 방향은 힘의 방향을 의미한다.
    예:
    Vector3(1, 0, 0) → 오른쪽으로 가속.
    Vector3(0, 1, 0) → 위로 가속.
    Vector2.right * 5 → 오른쪽으로 힘을 5만큼 가함.

  2. mode (선택):
    힘을 가하는 방식. 기본값은 ForceMode.Force 또는 ForceMode2D.Force이다.
    ForceMode 옵션:
    Force:
    일정한 힘을 가하여 가속(운동량의 변화)을 만든다. (뉴턴의 제2법칙 적용: F = ma)
    매 프레임마다 호출하면, 힘이 누적되어 속도가 계속 증가.
    Impulse:
    순간적으로 힘을 가해 물체를 빠르게 움직이게 한다. (운동량 = 힘 × 시간)
    주로 점프나 충돌 시 사용.
    VelocityChange:
    물체의 속도를 바로 변경합니다. 물리적인 질량(Mass)과 무관하게 작동.
    Acceleration:
    질량에 관계없이 가속도만 추가.

주요 특징

  1. 물리 엔진에 의해 처리:
    AddForce를 호출하면, 물리 엔진이 프레임마다 계산하여 힘의 효과를 반영한다.
    중력, 마찰력, 질량과 같은 물리 요소가 영향을 준다.

  2. 질량의 영향을 받음:
    가벼운 물체는 같은 힘에서 더 많이 가속되고, 무거운 물체는 덜 가속된다.

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

0개의 댓글