반응형


다양한 장르의 게임에서 많이 사용되는 점프 기능을 넣어보도록 할게요




바닥 역할을 해 줄 오브젝트와 조작할 플레이어 캐릭터를 생성해줍니다.

저는 Capsule로 플레이어 오브젝트를 시킬껀데 Cube나 다른 오브젝트들로 해도 괜찮습니다 :D 

그리고 물리적인 효과가 들어가야 해서 Rigidbody 컴포넌트를 추가시켜주세요 ~


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
 
public class PlayerController : MonoBehaviour {
 
    private Rigidbody rigid;
 
    public int JumpPower;
    public int MoveSpeed;
 
    void Start()
    {
        rigid = GetComponent<Rigidbody>();      //Rigidbody 컴포넌트를 받아옴
    }    
 
    void Update () {
        Move();
        Jump();
    }
 
    void Move ()
    {
        float h = Input.GetAxis("Horizontal");
        float v = Input.GetAxis("Vertical");
 
        transform.Translate((new Vector3 (h, 0, v) * MoveSpeed) * Time.deltaTime);
    }
 
    void Jump ()
    {
        if (Input.GetKeyDown(KeyCode.Space))
        {
            rigid.AddForce(Vector3.up * JumpPower, ForceMode.Impulse);
        }
    }
}
 
cs

그리고 스크립트를 작성해줍니다.

점프만 하면 재미 없으니까 저는 캐릭터를 움직일 수 있게 Move 함수를 만들어 줬어요. 점프와는 상관없으니까 추가시키지 않아도 무방합니다 !

점프는 if (Input.GetKeyDown(KeyCode.Space)) 스페이스 바를 누르면 발동하게 해줬는데

rigid.AddForce(Vector3.up * JumpPower, ForceMode.Impulse); 이 부분이 점프를 시켜주는 부분 입니다. 리지드바디에 힘을 추가(AddForce) 해주는 아이인데 '(벡터방향 (* 힘), (ForceMode))'로 이루어져 있습니다.

ForceMode는 총 4가지가 존재하는데 제가 사용한 ForceMode.Impulse 은 리지드바디 컴포넌트요소중에 Mass(질량)의 영향을 받으며 짥은 순간에 힘을 가하는 모드입니다.

혹여 다른 모드들이 궁금하거나 필요하신 분들은 [ 레퍼런스 URL <-클릭 ]로 이동하셔서 참고해주세요 ~


스크립트를 저장해주고 플레이어 오브젝트에 추가시켜줍니다. 값도 적당히 넣어주세요.

(저는 인스펙터에서 값을 조절하기 위해 public으로 선언해놓았습니다.)


실행시켜보면 Move 함수로 오브젝트가 움직여지고 Jump 함수로 오브젝트가 튀어오르는 걸 볼 수 있습니다 ~




하지만 겉보기에는 아무 문제 없어보이지만 두가지 문제가 있습니다.

첫번 째, 오브젝트가 가끔 뒤뚱거리다가 넘어져버림.

두번 째, 점프버튼을 연타하면 무한하게 점프가 가능


이 두 가지 문제를 해결해볼게요.



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
 
public class PlayerController : MonoBehaviour {
 
    private Rigidbody rigid;
 
    public int JumpPower;
    public int MoveSpeed;
 
    private bool IsJumping;
    
    void Start()
    {
        rigid = GetComponent<Rigidbody>();      //Rigidbody 컴포넌트를 받아옴
        IsJumping = false;                      //점프 중인지 판단할 수 있도록 bool 값 생성, 초기화
    }    
 
    void Update () {
        Move();
        Jump();
    }
 
    void Move ()
    {
        float h = Input.GetAxis("Horizontal");
        float v = Input.GetAxis("Vertical");
 
        transform.Translate((new Vector3 (h, 0, v) * MoveSpeed) * Time.deltaTime);
    }
 
    void Jump ()
    {
        //스페이스 키를 누르면 점프
        if (Input.GetKeyDown(KeyCode.Space))
        {
            //바닥에 있으면 점프를 실행
            if (!IsJumping)
            {
                //print("점프 가능 !");
                IsJumping = true;
                rigid.AddForce(Vector3.up * JumpPower, ForceMode.Impulse);
            }
 
            //공중에 떠있는 상태이면 점프하지 못하도록 리턴
            else
            {
                //print("점프 불가능 !");
                return;
            }
        }
    }
 
    private void OnCollisionEnter(Collision collision)
    {
        //바닥에 닿으면
        if (collision.gameObject.CompareTag("Ground"))
        {
            //점프가 가능한 상태로 만듦
            IsJumping = false;
        }
    }
}
 
cs

먼저 점프가 무한으로 실행되는 문제는 해결할게요. 이건 여러가지 방법이 있긴한데 제일 간단하다고 생각하는 방식으로 하겠습니다.

private void OnCollisionEnter(Collision collision) 에서

if (collision.gameObject.CompareTag("Ground")) 'Ground' 라는 Tag를 가진 오브젝트와 접촉하는 순간 IsJumping = false; 점프상태를 false로 만들어줍니다.


풀어서 말하면

if (!IsJumping)
            {
                print("점프 가능!");
                IsJumping = true;
                rigid.AddForce(Vector3.up * JumpPower, ForceMode.Impulse);
            }

점프를 하는 순간 점프가 불가능 한 상태로 IsJumping = true; 만들어주고


if (collision.gameObject.CompareTag("Ground"))
        {
            //점프가 가능한 상태로 만듦
            IsJumping = false;
        }

착지하는 순간 점프가 가능하도록 IsJumping = false; 로 만들어주는 겁니다.

그러면 땅에 닿아있지 않고 공중에 떠있는 상황에선 'IsJumping' 이 true 상태이기 때문에 점프가 발동되지 않고 땅에 닿는 순간 'IsJumping' 이 false 상태로 바뀌기 때문에 다시 점프가 가능하게 되는 겁니다.


바닥 역할을 하고 있는 오브젝트에 태그를 추가시켜 줍니다.

저는 스크립트에서 Ground라고 해놨기 때문에 태그 추가도 Ground라고 설정합니다.

만약 다른 태그로 하실 분들은 임의로 스크립트와 태그명을 정해주시면 됩니다.


공중에 있을 때 점프키를 입력하면 "점프 불가능"

지상에 있을 때 점프키를 입력하면 "점프 가능"

이라고 디버그 되도록 해놓고 실행 시켰습니다.

공중에선 다시 점프가 실행되지 않는 모습을 볼 수 있습니다.


이제 간혹 플레이어 오브젝트가 넘어져버리는 문제가 남아있는데 아주아주 간단합니다.

리지드바디 컴포넌트에 'Constraints' 설정이 숨겨져 있는 상태일텐데 클릭해서 열어보시면 저런 옵션이 나옵니다. 저기서 X와 Z에 체크하시면 오브젝트가 넘어지지 않게 됩니다.

(저는 Cube같이 각져있는 오브젝트로 하지 않아서 발생하는 문제입니다. 만약 바닥면이 반듯한 모델의 오브젝트에 적용했다면 발생하지 않는 문제입니다. 그래도 혹시나 모를 문제를 방지 할 수 있으니 만약 바닥면이 반듯한 모델 오브젝트여도 적용하시는 걸 추천합니다.)





이제 플레이어가 조작하는 오브젝트가 점프를 할 수 있게 됐네요 ~

반응형
  • 네이버 블러그 공유하기
  • 네이버 밴드에 공유하기
  • 페이스북 공유하기
  • 카카오스토리 공유하기