DNF LOVE

[Unity-2D 러닝 게임 만들기 3] 사용자 입력에 따라 플레이어가 이동하고 물리엔진을 통해 Jump를 구현해보도록 하자!(충돌체, 물리엔진) 본문

Programming/Unity

[Unity-2D 러닝 게임 만들기 3] 사용자 입력에 따라 플레이어가 이동하고 물리엔진을 통해 Jump를 구현해보도록 하자!(충돌체, 물리엔진)

botho 2019. 7. 30. 00:29
반응형

1. Collider, Rigidbody 

우리는 이전에 위와 같은 상태로 포스팅을 끝마쳤다. 이 상태로 ctrl+p를 누르거나 실행 버튼을 누르면 어떻게 되는가?

우리가 원하는 모습은 플레이어가 바닥에 붙는 모습을 상상하였는데 아쉽게도 우리가 모양을 잡아준대로 오브젝트들이 존재한다.

그렇다면 플레이어가 바닥에 붙이게 하기 위해선 어떻게 해야 할까?

정답은 '충돌'과 '물리엔진'이다.

앞전 포스팅에서 Unity에서 물리엔진은 'Rigidbody'라고 배웠는데 3D용과 2D용이 따로 있다.

물리엔진이 필요한 친구는 플레이어 뿐이므로 플레이어에게 Rigidbody2D를 붙여주도록 하자.

붙이고 게임을 실행하면 어떻게 되는가? 플레이어가 무한으로 바닥으로 떨어진다.

이를 방지하기 위해선 무엇을 해야할까?

정답은 '충돌체'이다.

충돌체 Collider란? 말 그대로 물체와 물체가 부딪칠때 그 효과를 나타내기 위해 존재하는 컴포넌트이다. 충돌체는 물리엔진과 같이 써야 한다.

물론 후에 Collider와 Trigger 등의 충돌체에 대해 설명 포스팅을 하겠지만 지금은 콜라이더의 자세한 사항은 유니티 API를 참고하도록 하자 - https://docs.unity3d.com/kr/530/ScriptReference/Collider.html

충돌체가 필요할 것 같은 애들은 무엇일까? 바닥, 장애물, 플레이어이다. 이들에게 각각 Box Collider 2D를 붙여주도록 하자.

충돌체를 붙여주면 어떻게 되는가? 플레이어는 바닥에 딱! 붙게 될 수 있게 되었다.


2. 사용자 입력에 따라 좌우 이동을 구현해보자.

이전 포스팅에서 만들어 뒀던 PlayerControler를 Player에게 붙여보도록 하자!(전 포스팅들을 보지 않았다면 Scripts폴더를 만들어서 PlayerControler라는 이름의 c# 스크립트를 새로 만들도록 하자)

그래픽스에서 3D와 2D가 다르게 적용되기 떄문에 Object들은 호환이 될 수 없지만 코드는 공유할 수 있다!

Edit -> Project Settings -> Input Manager 을 확인해 보면 Unity에서 지원해주는 입력 명들을 확인할 수 있다.

우리는 전 포스팅들을 통해 3D에서 사용자 입력에 따라 오브젝트가 움직이는 것 까지 구현해보았다.

public class PlayerControler : MonoBehaviour
{
    public float speed = 10f;

    private Rigidbody rd;

    Vector3 move;

    void Start()
    {
        rd = this.gameObject.GetComponent<Rigidbody>();

        move = this.gameObject.transform.position;
    }

    void Update()
    {
        float movespeed = speed * Time.deltaTime;

        float h = Input.GetAxisRaw("Horizontal");
        float v = Input.GetAxisRaw("Vertical");

        // 이동거리 보정
        h = h * movespeed;
        v = v * movespeed;

        // 실제 이동
        transform.Translate(Vector3.right * h);
        transform.Translate(Vector3.forward * v);
    }
}

이렇게 된 상태에서 실행을 하면 어떻게 될까?

와 일단 speed가 너무 빠르니 3f쯤으로 수정해주고 점프를 하고 싶은데 플레이어가 갑자기 사라져버렸다!

Jump를 구현하려고 한다면 어떻게 해야 할까?


3. 점프점프! Jump를 구현해보자!

다시 또 Edit -> Project Settings -> Input Manager 를 확인해 보면 Axes에서 Jump를 확인할 수 있다. 

PC에서 Jump입력 버튼은 스페이스 버튼이다. 앞전 Horizontal과 Vertical과 같이 구현해보도록 하자.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class PlayerControler : MonoBehaviour
{
    public float speed = 3f;

    private Rigidbody rd;

    Vector3 move;

    void Start()
    {
        rd = this.gameObject.GetComponent<Rigidbody>();

        move = this.gameObject.transform.position;
    }

    void Update()
    {
        float movespeed = speed * Time.deltaTime;

        float h = Input.GetAxisRaw("Horizontal");
        float v = Input.GetAxisRaw("Vertical");
        float j = Input.GetAxisRaw("Jump");

        // 이동거리 보정
        h = h * movespeed;
        v = v * movespeed;
        j = j * movespeed;

        // 실제 이동
        transform.Translate(Vector3.right * h);
        transform.Translate(Vector3.forward * v);
        transform.Translate(Vector3.up * j);

    }
}

2D 좌표 기준 위의 벡터 방향은 Y방향으로 (0, 1, 0) 방향이다. 

Jump 버튼에 따라 speed와 time.deltatime을 곱해주며 Vector3.Up - (0, 1, 0)방향으로 가해진 힘 만큼 올라가게 구현하였다.

(*** time.deltatime은 지난 프레임이 완료되는 데 까지 걸린 시간을 나타내며, 단위는 초를 사용한다.

time.deltatime을 쓰는 이유는 Object를 연속적으로 이동시키거나 회전시킬 때 Update() 혹은 FixedUpdate()에서 구현해야 한다. FixedUpdate같은 경우 독립적인 타이머를 호출하지만 Update구문 같은 경우 연속적으로 오브젝트가 변화될 때 사용되어야 한다. 왜냐하면 매 프레임 마다 호출되는 Update() 특성 상 디바이스 성능에 따라 프레임 횟수가 다르기 때문에 문제가 발생되기 때문이다. (프레임 횟수가 다르면 움직이는 속도가 달라진다) 이는 Time.deltatime 이전 프레임이 완료되기까지 걸린 시간으로 성능이 느릴수록 값이 커지는 특성을 담고 있기 때문에 이를 통해 해결할 수 있다.)

이제 실행해 보도록 하자!

어떤가? 이번에는 속도도 조금 느린 것 같고 장애물의 높이에 비해 오브젝트가 장애물을 넘지 못했다!

이럴때에는 speed변수를 4f로 바꾸어주고 이동 거리를 보정하는 부분이나, 실제 이동거리를 하는 코드 쪽에 Jump부분만 * 1.5f를 해보도록 하자.

public class PlayerControler : MonoBehaviour
{
    public float speed = 4f;

    private Rigidbody rd;

    Vector3 move;

    void Start()
    {
        rd = this.gameObject.GetComponent<Rigidbody>();

        move = this.gameObject.transform.position;
    }

    void Update()
    {
        float movespeed = speed * Time.deltaTime;

        float h = Input.GetAxisRaw("Horizontal");
        float v = Input.GetAxisRaw("Vertical");
        float j = Input.GetAxisRaw("Jump");

        // 이동거리 보정
        h = h * movespeed;
        v = v * movespeed;
        j = j * movespeed;

        // 실제 이동
        transform.Translate(Vector3.right * h);
        transform.Translate(Vector3.forward * v);
        transform.Translate(Vector3.up * j * 1.5f);

    }
}

흠.. 다 좋은 것 같은데 플레이어가 장애물과 부딪치게 되면 구 모양이기에 회전하게 된다. 이렇게 되면 이동할때나 점프할때나 힘의 방향이 이상하게 가기 때문에 회전되지 않게 막아줘야 한다. 

그럴 떄 rigidbody의 Contains -> freeze Rotation에서 z축이 회전되지 않도록 막아줘야 한다. 또 점프가 좀 시원찮으니 1.5f곱해주던걸 2f만큼 곱해주자.

와! 이제 제대로 된 캐릭터가 된 것 같다.

다음은 UI/UX를 다루어보며 Score 항목을 만들어 보도록 하자.

반응형