Wiem, czy robię zbyt wiele rzeczy w update() Konsekwencją zostanie upuszczona wskaźnik klatek poniżej celu. Ale co by się stało, jeśli zrobię to samo w fixedUpdate()?

Czy spowodowałoby, że fizyka jedności, by się zepsuć, czy też spowoduje awarię programu?

3
AVAVT 16 luty 2017, 15:16

2 odpowiedzi

Najlepsza odpowiedź

Odpowiedzi i komentarze były bardzo pomocne, ale brakuje im wyraźnej, pouczającej odpowiedzi na moje pytanie. Wszyscy wiedzą, że złe rzeczy się wydarzy, gdy umieściłeś zbyt dużo obciążenia pracy w pętli FixedUpdate(), moje pytanie było zapytanie co się wydarzy.

Odkąd w końcu dostałem rękę na komputerze, postanowiłem zrobić jakiś test sam. Właśnie w odniesieniu do tego, co kiedyś testowałem:

public class TestFixedUpdate : MonoBehaviour {
    public int loopNo = 500000;

    private int noOfCall = 0;
    private int collisionTimes = 0;

    private void FixedUpdate()
    {

        if (noOfCall > 100) return;
        float time = Time.timeSinceLevelLoad;

        for (int i = 0; i < loopNo; i++) {
            Quaternion.Slerp(Quaternion.identity, Quaternion.FromToRotation(Vector3.up, Vector3.forward), Mathf.Abs(Mathf.Sin(Time.timeSinceLevelLoad)));
        }

        Debug.Log(Time.timeSinceLevelLoad.ToString("0.00"));

        if (noOfCall > 99) Debug.Log("Simulation finished. Times collided:" + collisionTimes);

        noOfCall++;
    }

    private void OnCollisionEnter(Collision collision)
    {
        if (noOfCall > 100) return;
        collisionTimes++;
        Debug.Log("Times collided:" + collisionTimes);
    }
}

Włożyłem go na sferę, która stale odbija się w samolocie. Test został wykonany przez zmianę funkcji z FixedUpdate() i Update() i porównaj różnice.

Główna różnica, którą dowiedziałem, że w przypadku FixedUpdate(), symulowane Time (czas na świecie) jest opóźniony z synchronizacji z rzeczywistym czasem. Innymi słowy, dowolna funkcja, która zależy od systemu Unity's {X2}}, będzie działać tak, jakby cały świat zwolnił.

Również:

  1. Jedność informuje o tej samej szybkości klatek dla obu przypadków, nawet jeśli dla przypadku FixedUpdate() jest oczywiste, że rzeczywista szybkość klatek - rama na drugi światowy - jest znacznie niższy.

  2. Oprócz spowolnienia, wykrywanie kolizji i logika symulacji fizyki wydają się działać jak zwykle. Ciała, które powinny zderzać się nadal? Przyspieszenie, zastosowanie siły itp. Sztywniki, które nie przeskakują przez kolbatora w 20 ms (MS Unity) wciąż zderzają się i odbijają jak zwykle.

  3. Opcja Maximum Allowed Timestep w ustawieniach projektu określa maksymalną ilość (symulowany czas Unity) przed naruszeniem ramy (nigdy nie wiedziałem, co to było na wcześniej). Wyjaśnienie: Jeśli ustawię go do 0,5 sekundy, bez względu na to, ile kodu umieściłem w obu funkcjach, etap aktualizacji logiki (Update()) zostanie wywołany natychmiast po rundzie {x2}} symulował 0,5- Po drugie, a potem scena zostanie renderowana.

3
AVAVT 16 luty 2017, 18:19

Silnik przechodzi podczas przetwarzania ciężkiego obciążenia (np. Jeśli wykonasz nieskończoną pętlę) w dowolnej funkcji. Rzeczy, które opierają się na czas To naprawdę nie ma znaczenia, czy jest to aktualizacja lub naprawa.

Co możesz zrobić, jeśli potrzebujesz sposobu uruchomienia ciężkiego ładunku, jest użycie coroutines np. Funkcja i wydajność IeMerator, która pozwala podzielić przetwarzanie przez wiele klatek, lub mieć pewną funkcję zwaną wywołaniem zwrotnym. na przykład Jeśli masz ścieżkę kontrolną AI 5 razy na sekundę, możesz obsługiwać, że w aktualizacji za pomocą licznika każdej klatki lub możesz zaplanować wywołanie zwrotne.

Zasadniczo będzie ograniczony, ile kodu można uruchomić na ramkę bez poniższej wydajności. Sprytne przepisywanie powinno to zrobić niepotrzebne. Sprawdź, czy możesz zaprojektować wyniki obliczeń lub wstępnie obliczyć jak najwięcej danych poza grą.

0
Jason Lang 16 luty 2017, 15:43