Menu
CoddyTech

직접 중력 구현하기

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

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에서 시작하기 때문입니다. 정지 상태에서 떨어지면, 반초 뒤에 컨트롤러의 속도는 초당 -4.9 단위가 되고 1초 뒤에는 -9.81이 됩니다.

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

challenge icon

챌린지

중급

다이버는 높은 탑 위에 서 있고, 화살표 키로 다이버를 움직입니다(이미 작성되어 있음). Diver.cs에 중력을 추가하세요. Inspector에서 gravity(-12)와 maxFall(10)을 설정하며, 스크립트에는 verticalSpeed 필드가 있습니다.

  • 매 프레임마다 verticalSpeed에 초당 gravity만큼 더하고, 걷기와 동일한 Move에서 다이버를 그만큼 아래로 움직입니다.
  • 공중에서는 긴 낙하 속도가 느려집니다. 다이버는 초당 maxFall단위보다 빠르게 떨어지지 않습니다.
  • 컨트롤러가 지면에 있고 verticalSpeed가 0보다 작으면 verticalSpeed를 -1로 설정하세요.

Play를 누르고 탑에서 걸어 내려온 다음 Check를 누르세요.

직접 해보기

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);
    }
}
quiz icon실력 점검

이 레슨에는 짧은 퀴즈가 포함되어 있습니다. 레슨을 시작해 문제를 풀고 진행 상황을 기록하세요.

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