Menu
CoddyTech

직접 중력 구현하기

Coddy Unity 여정의 실제 게임 만들기 섹션에 포함된 레슨. 60개 중 39번째.

CharacterController는 스크립트가 떨어지도록 해야만 떨어지며, 실제로 떨어질 때는 속도가 빨라집니다. 중력은 매초 낙하 속도에 초당 약 9.81단위를 더합니다. 따라서 스크립트는 필드에 수직 속도를 저장하고, 매 프레임 속도에 gravity * Time.deltaTime을 더한 다음, 걷기와 같은 Move에서 그 속도만큼 이동합니다.

public float gravity = -9.81f;
float verticalSpeed;

void Update()
{
    if (controller.isGrounded && verticalSpeed < 0f)
    {
        verticalSpeed = -2f;   // 지면에 있을 때: 낙하를 멈추고 아래쪽으로 약하게 누르는 힘을 유지
    }
    verticalSpeed += gravity * Time.deltaTime;

    Vector3 move = new Vector3(Input.GetAxisRaw("Horizontal"), 0f, Input.GetAxisRaw("Vertical")) * speed;
    move.y = verticalSpeed;
    controller.Move(move * Time.deltaTime);
}

Time.deltaTime은 두 가지 역할로 두 번 등장합니다. gravity * Time.deltaTime은 이번 프레임에 증가한 속도이고, 속도에 Time.deltaTime을 곱한 값은 이번 프레임에 이동한 거리입니다. 속도는 프레임마다 유지되어야 하므로 필드에 저장합니다. 지역 변수는 매 프레임 다시 0에서 시작합니다. 정지 상태에서 떨어지면, 컨트롤러의 속도는 0.5초 후 초당 -4.9단위, 1초 후 초당 -9.81단위가 됩니다.

초기화는 낙하만큼 중요합니다. 바닥에서는 Move가 컨트롤러를 멈추지만, 필드의 값은 멈추지 않습니다. 초기화하지 않으면 플레이어가 서 있는 동안에도 값이 계속 커지고, 다음에 절벽에서 발을 내딛을 때 최대 속도로 떨어집니다. 0이 아니라 작은 음수로 초기화하는 이유는 모든 Move가 계속 바닥을 누르게 하기 위해서입니다. 프레임 속도가 높을 때는 한 프레임 동안 중력이 가하는 힘이 Min Move Distance보다 작을 수 있으며, 그러면 Move가 아무 동작도 하지 않고 isGrounded가 false로 바뀝니다. isGrounded는 Move 전에 읽으므로 이전 프레임의 Move 상태를 나타냅니다.

challenge icon

챌린지

중급

다이버에게 중력을 적용해 낙하 속도가 빨라지게 하세요.

  1. Update()의 맨 위에서 controller.isGrounded가 참이고 verticalSpeed < 0f일 때 verticalSpeed = -1f;로 설정하세요.
  2. gravity * Time.deltaTime을 더하고, Mathf.Max를 사용해 값이 -maxFall 이상이 되도록 유지하세요.
  3. controller.Move 줄 앞에서 move.y = verticalSpeed;로 설정하세요.

‘플레이’를 누르고 탑에서 걸어 내려오세요. 낙하 속도가 초당 10유닛까지 빨라집니다. 그런 다음 ‘확인’을 누르세요.

직접 해보기

using UnityEngine;

public class Diver : MonoBehaviour
{
    public float speed = 4f;
    public float gravity = -12f;
    public float maxFall = 10f;

    CharacterController controller;
    float verticalSpeed;

    void Start()
    {
        controller = GetComponent<CharacterController>();
    }

    void Update()
    {
        // 중력: 지면에 있을 때 verticalSpeed를 초기화하고, 중력을 적용하고, 낙하 속도를 제한한 뒤 move.y에 넣습니다

        Vector3 move = new Vector3(Input.GetAxisRaw("Horizontal"), 0f, Input.GetAxisRaw("Vertical")) * speed;
        controller.Move(move * Time.deltaTime);
    }
}

실제 게임 만들기의 모든 레슨

직접 연습해 보세요: Unity 플레이그라운드