프로젝트/Unity로 공포게임 개발

[Unity 공포게임] 1인칭 플레이어 이동, 마우스로 카메라 시점 조작(2) - 오브젝트에 중력 적용하기

코멍이 2023. 3. 30. 21:40

1인칭 플레이어 이동, 마우스로 카메라 시점 조작 (2) - 오브젝트에 중력 적용하기

 

<목차>

1. 키보드로 오브젝트 이동하기
     1-1. transform.position을 이용하기
     1-2. transform.Translate을 이용하기
     1-3. Inptut.GetAxis()를 이용하기
     1-4. CharatcerController를 이용하기
     1-5. 1인칭 시점 적용하기

2. 오브젝트에 중력 적용하기
3. 마우스로 카메라 시점 조작하기

 

 


 

 

2. 오브젝트에 중력 적용하기

 

 

 

지난 게시글에 이어 이번에는 오브젝트에 중력을 적용하는 방법을 알아보자. 중력을 설정하지 않으면 Character Controller를 사용한다 하더라도 위 이미지와 같은 상황이 발생하고 만다.

 

 

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

public class PlayerMove : MonoBehaviour
{
    [SerializeField] float speed=5f;
    private CharacterController controller;

    // Start is called before the first frame update
    void Start()
    {
        controller = GetComponent<CharacterController>();
    }

    // Update is called once per frame
    void Update()
    {
        float h = Input.GetAxis("Horizontal");
        float v = Input.GetAxis("Vertical");
        Vector3 mov = new Vector3(h, 0, v);
        this.transform.Translate(mov * Time.deltaTime * speed);

    }
}

 

 

우선 지난 게시글에서 사용한 코드를 그대로 가져와보았다. start메소드에서 CharacterController를 받고 GetAxis를 이용해 움직임을 구현해주었다. 이제 이 코드에 중력을 구현해볼 차례이다.

 

 

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

public class PlayerMove : MonoBehaviour
{
    [SerializeField] float speed=5f; //이동속도
    private float gravity; //중력
    private CharacterController controller; //캐릭터 컨트롤러
    private Vector3 mov; //방향


    // Start is called before the first frame update
    void Start()
    {
        controller = GetComponent<CharacterController>();
        mov = Vector3.zero; //벡터 초기화
        gravity = 10f; //중력값 설정
    }

    // Update is called once per frame
    void Update()
    {
        float h = Input.GetAxis("Horizontal");
        float v = Input.GetAxis("Vertical");
        Vector3 mov = new Vector3(h, 0, v);
        this.transform.Translate(mov * Time.deltaTime * speed);

    }
}

 

우선 코드를 한 번 정리하고 중력 수치를 담을 gravity변수를 추가하였다.

Vector3 mov를 전역 변수로 선언한 다음, start메소드에서 (0,0,0)으로 초기화를 해주었다.

중력의 값은 10이라는 임의의 값을 지정해주었다. project setting에서 확인한 physisc의 gravity값이 아래와 같았기 때문!

 

 

 

 

physics의 gravity는 rigidbody(물리엔진)에 적용되는 중력의 수치를 나타낸다. 사용자의 입맛에 맞게 바꾸어 줄수도 있는 것 같지만 지금은 일단 그대로 사용하기로 했다.

 

 

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

public class PlayerMove : MonoBehaviour
{
    [SerializeField] float speed=5f;
    private float gravity;
    private CharacterController controller;
    private Vector3 mov;


    // Start is called before the first frame update
    void Start()
    {
        controller = GetComponent<CharacterController>();
        mov = Vector3.zero;
        gravity = 10f;
    }

    // Update is called once per frame
    void Update()
    {
        mov = new Vector3(Input.GetAxis("Horizontal"), 0, Input.GetAxis("Vertical"));
        controller.Move(mov * Time.deltaTime * speed);

    }
}

 

update메소드에서 mov 부분을 조금 더 간결하게 만들어준 뒤, 이번에는 transform.Translate을 이용하는 것이 아닌 Character Controller 자체의 메소드인 Move를 사용하여 움직임을 구현해보았다. Move 메소드는 오브젝트 자체의 position값을 수정하는 것이 아닌 오브젝트에 추가된 Character Controller를 이용하여 움직임을 구현하는 방식이다.

 

 

 

 

transform.Translate 대신 Move를 사용하니 캐릭터가 드디어 경사면을 오를 수 있게 되었다.

 

 

 

 

 

그런데 뭔가 이상하다. 경사면을 오른 것 까지는 좋은데 캐릭터가 내려오질 않고 공중을 떠다니고 있다. 이것은 우리가 변수에 중력 값을 넣어두기만 했을 뿐, 실제로 구현은 하지 않았기 때문이다.

 

 

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

public class PlayerMove : MonoBehaviour
{
    [SerializeField] float speed=5f;
    private float gravity;
    private CharacterController controller;
    private Vector3 mov;


    // Start is called before the first frame update
    void Start()
    {
        controller = GetComponent<CharacterController>();
        mov = Vector3.zero;
        gravity = 10f;
    }

    // Update is called once per frame
    void Update()
    {
        if (controller.isGrounded)
        {
            mov = new Vector3(Input.GetAxis("Horizontal"), 0, Input.GetAxis("Vertical"));
        }
        else
        {
            mov.y -= gravity * Time.deltaTime;
        }
        
        controller.Move(mov * Time.deltaTime * speed);

    }
}

 

isGrounded는 CharacterController가 지면에 붙어있는지 아닌지를 판별하고 지면에 닿아있을 경우 true 값을 반환한다. 위 코드는 만약 controller가 지면에 붙어 있지 않다면 프레임마다 mov의 y값에 '-중력값' 만큼을 더해준다. y값이 계속해서 음수로 떨어지므로 오브젝트 역시 밑으로 추락하게 되는 것이다.

 

 

 

무사히 중력이 적용된 모습.

캡슐은 더이상 공중부양을 하지 않고 지면에서 벗어나면 추락하게 된다.

 

 


 

이제 남은 것은 캐릭터의 방향을 원하는 쪽으로 바꾸어주는 것이다.

1인칭 게임에서는 키보드로 캐릭터의 움직임을 조작하고 마우스로 방향을 바꾸고는 한다.

 

다음 게시글에서는 이어서 마우스로 캐릭터의 방향을 설정해보도록 하겠다.