Menu
CoddyTech

Grawitacja ręcznie

Część sekcji Tworzenie prawdziwych gier ścieżki Unity w Coddy. Lekcja 38 z 56.

CharacterController spada tylko wtedy, gdy skrypt sprawia, że spada, a rzeczywisty upadek przyspiesza: grawitacja dodaje około 9.81 jednostki na sekundę do prędkości spadania w każdej sekundzie. Dlatego skrypt przechowuje prędkość pionową w polu, dodaje do niej gravity * Time.deltaTime w każdej klatce i przemieszcza obiekt o tę wartość w tym samym wywołaniu Move co podczas chodzenia:

public float gravity = -9.81f;
float verticalSpeed;

void Update()
{
    if (controller.isGrounded && verticalSpeed < 0f)
    {
        verticalSpeed = -2f;   // na ziemi: zakończ opadanie, zachowaj lekki nacisk w dół
    }
    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 pojawia się dwa razy i za każdym razem pełni inną funkcję: gravity * Time.deltaTime to prędkość uzyskana w tej klatce, a prędkość pomnożona przez Time.deltaTime to odległość pokonana w tej klatce. Prędkość jest polem, ponieważ musi być zachowana z klatki na klatkę; zmienna lokalna zaczynałaby od 0 w każdej klatce. Spadając z miejsca, CharacterController osiąga prędkość -4.9 jednostki na sekundę po pół sekundy i -9.81 po jednej sekundzie.

Reset jest równie ważny jak sam upadek. Na podłożu Move zatrzymuje CharacterController, ale nic nie zatrzymuje pola: bez resetu jego wartość stale rośnie, gdy gracz stoi, a po zejściu z krawędzi gracz spada z pełną prędkością. Prędkość jest resetowana do niewielkiej wartości ujemnej zamiast do 0, dzięki czemu każde wywołanie Move nadal dociska postać do podłoża: przy dużej liczbie klatek na sekundę siła grawitacji działająca przez jedną klatkę może być mniejsza niż Min Move Distance, Move nic nie robi, a isGrounded przyjmuje wartość false. Odczyt isGrounded następuje przed wywołaniem Move, więc opisuje działanie Move z poprzedniej klatki.

challenge icon

Wyzwanie

Średni

Nurek stoi na wysokiej wieży, a strzałki nim poruszają (to już jest napisane). Dodaj grawitację w Diver.cs. W Inspectorze ustaw gravity (-12) i maxFall (10), a skrypt ma pole verticalSpeed.

  • W każdej klatce verticalSpeed zwiększa się o gravity na sekundę, a nurek porusza się w dół o tę wartość w tym samym wywołaniu Move, co podczas chodzenia.
  • Opór powietrza spowalnia długi upadek: nurek nigdy nie spada szybciej niż maxFall jednostek na sekundę.
  • Gdy kontroler wykrywa podłoże, a verticalSpeed jest mniejsze od 0, ustaw verticalSpeed na -1.

Naciśnij Play, zejdź z wieży, a następnie naciśnij Check.

Spróbuj swoich sił

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()
    {
        // Grawitacja: na ziemi zresetuj verticalSpeed, dodaj grawitację, ogranicz prędkość opadania i przypisz ją do move.y

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

Ta lekcja zawiera krótki quiz. Zacznij lekcję, żeby na niego odpowiedzieć i śledzić swoje postępy.

Wszystkie lekcje w sekcji Tworzenie prawdziwych gier