유니티에서 이동 및 점프하는 법 (플랫포머 게임)
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.GetAxis 의 차이점
Input.GetAxisRaw는 유니티에서 입력 장치(키보드, 조이스틱, 마우스 등)로부터 입력 값을 가져오는 함수다.
즉각적이고 간단한 디지털 입력 처리가 필요할 때 유용하다. (2D 플랫폼 게임처럼 빠른 반응이 중요한 게임)
유니티에서 FixedUpdate를 사용하는 이유는 물리 연산과 관련된 작업을 정확하고 안정적으로 처리하기 위해서다.
주요 특징으로
고정된 호출 간격:
FixedUpdate는 게임 프레임 속도와 관계없이 일정한 간격으로 호출된다.
물리 엔진이 매 프레임이 아닌 고정된 시간 간격(기본 0.02초)에 따라 동작하므로, 물리 연산(예: 속도, 힘, 충돌 등)을 일관되게 처리한다.
물리 연산에 적합:
유니티의 물리 시스템(예: Rigidbody, Collider 등)은 FixedUpdate에서 처리되도록 설계되었다.
Rigidbody.AddForce와 같은 물리 연산은 FixedUpdate에서 호출해야 정상적으로 동작하며, 부정확한 결과를 방지할 수 있다.
Time.deltaTime과 차이점:
FixedUpdate는 Time.fixedDeltaTime(고정 시간 간격)을 사용한다.
Update에서의 Time.deltaTime은 프레임마다 변할 수 있지만, FixedUpdate에서는 항상 일정한 값을 갖는다.
이동 및 점프를 Update에 코딩하면 컴퓨터의 성능에 따라서 적용되는 속도가 다를 수 있다.
Mathf.Abs는 유니티의 Mathf 클래스에서 제공하는 함수로, 주어진 숫자의 절대값(Absolute Value)을 반환한다.
절대값은 숫자의 부호를 제거한 값으로, 양수와 음수 모두 0 또는 양수로 변환된다.
즉, 음수는 양수로, 양수는 그대로 반환된다.
사용하는 이유로
부호와 관계없이 값을 비교하거나 처리해야 할 때.
음수 값으로 인한 오류를 방지:
예를 들어, 거리나 속도처럼 항상 양수로 표현되어야 하는 값.
다양한 수학적/게임 로직에서 필수적:
충돌 거리 계산, 속도 제한, 점수 차 계산 등.
유니티의 Rigidbody.AddForce 메서드는 Rigidbody에 특정 방향과 크기의 힘(Force)을 가하여 물체를 움직이는 데 사용된다.
2D 물리에서는 Rigidbody2D.AddForce로 동일하게 동작한다.
매개변수
force (필수):
힘의 방향과 크기를 나타내는 벡터.
벡터 크기(Magnitude)는 힘의 세기를, 벡터 방향은 힘의 방향을 의미한다.
예:
Vector3(1, 0, 0) → 오른쪽으로 가속.
Vector3(0, 1, 0) → 위로 가속.
Vector2.right * 5 → 오른쪽으로 힘을 5만큼 가함.
mode (선택):
힘을 가하는 방식. 기본값은 ForceMode.Force 또는 ForceMode2D.Force이다.
ForceMode 옵션:
Force:
일정한 힘을 가하여 가속(운동량의 변화)을 만든다. (뉴턴의 제2법칙 적용: F = ma)
매 프레임마다 호출하면, 힘이 누적되어 속도가 계속 증가.
Impulse:
순간적으로 힘을 가해 물체를 빠르게 움직이게 한다. (운동량 = 힘 × 시간)
주로 점프나 충돌 시 사용.
VelocityChange:
물체의 속도를 바로 변경합니다. 물리적인 질량(Mass)과 무관하게 작동.
Acceleration:
질량에 관계없이 가속도만 추가.
주요 특징
물리 엔진에 의해 처리:
AddForce를 호출하면, 물리 엔진이 프레임마다 계산하여 힘의 효과를 반영한다.
중력, 마찰력, 질량과 같은 물리 요소가 영향을 준다.
질량의 영향을 받음:
가벼운 물체는 같은 힘에서 더 많이 가속되고, 무거운 물체는 덜 가속된다.