Menu
CoddyTech

Grawitacja ręcznie

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

CharacterController opada tylko wtedy, gdy skrypt sprawia, że opada, a rzeczywisty spadek przyspiesza: grawitacja dodaje do prędkości opadania około 9.81 jednostki na sekundę w każdej sekundzie. Dlatego skrypt przechowuje prędkość pionową w polu, dodaje do niej co klatkę gravity * Time.deltaTime 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 spadanie, utrzymuj lekką siłę skierowaną 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 przyrost prędkości w tej klatce, a prędkość pomnożona przez Time.deltaTime to odległość pokonana w tej klatce. Prędkość jest przechowywana w polu, ponieważ musi być zachowana z klatki na klatkę; zmienna lokalna zaczynałaby od 0 w każdej klatce. Spadając od spoczynku, kontroler po pół sekundy osiąga prędkość -4.9 jednostki na sekundę, a po jednej sekundzie -9.81.

Reset jest równie ważny jak sam spadek. Na podłożu Move zatrzymuje kontroler, 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ą. Wartość jest resetowana do niewielkiej liczby ujemnej zamiast do 0, dzięki czemu każde wywołanie Move nadal dociska obiekt do podłoża: przy wysokiej liczbie klatek na sekundę siła nacisku wywołana grawitacją w jednej klatce może być mniejsza niż Min Move Distance, Move nic nie zrobi, a isGrounded przyjmie wartość false. isGrounded jest odczytywane przed wywołaniem Move, więc opisuje działanie Move z poprzedniej klatki.

challenge icon

Wyzwanie

Średni

Dodaj grawitację nurkowi, aby jego spadanie przyspieszało.

  1. Na początku Update(), gdy controller.isGrounded i verticalSpeed < 0f, ustaw verticalSpeed = -1f;.
  2. Dodaj do niej gravity * Time.deltaTime i utrzymuj ją na poziomie -maxFall lub wyższym, używając Mathf.Max.
  3. Przed linią controller.Move ustaw move.y = verticalSpeed;.

Naciśnij „Graj” i zejdź z wieży: spadanie przyspieszy do 10 jednostek na sekundę. Następnie naciśnij „Sprawdź”.

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: zresetuj verticalSpeed na ziemi, dodaj grawitację, ogranicz prędkość spadania i przypisz wynik do move.y

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

Wszystkie lekcje w sekcji Tworzenie prawdziwych gier

Poćwicz samodzielnie: Edytor online Unity