Ancora un altro articolo su quando utilizzare i metodi Update e FixedUpdated.
TD;LR: Avendo abbastanza facilmente, ricreato il problema di miscelazione e la congruenza timesteps, ho convinto me stesso che avrei dovuto mettere tutti stato del gioco in FixedUpdate metodi.
Prima di entrare nel merito di questo articolo, volevo chiarire perché sono interessato all’unità in primo luogo:
- NON ho molto interesse a giocare e la creazione di video giochi
- io NON ho un interesse per la costruzione di strumenti utili (sono un web-developer per MOLTI anni)
- io NON sono un early adopter
- l’Unità è ormai CONSOLIDATA la soluzione per la creazione di multi-piattaforma di esperienze 3D
Con tutto questo in mente, edificio pratico web-powered Realtà Aumentata (AR) soluzioni con l’Unità è qualcosa che ho bisogno di imparare.
Per quanto riguarda l’apprendimento di Unity, NON ho trovato particolarmente utili i tutorial ufficiali di Unity. Ho trovato il corso Udemy Learn Unity 3D per principianti assoluti per essere eccellente.
Stavo navigando attraverso i materiali e mi sono trovato appeso alla differenza di lezione tra Update e FixedUpdate. Ricercando un po ‘ di più, il nocciolo del problema era che non capivo la seguente logica.
Update();… Usato per aggiornamenti regolari come: Spostamento di oggetti non fisici
FixedUpdate ();… Usato per aggiornamenti regolari come: Regolazione degli oggetti fisici (Rigidbody)
Unity — Update and FixedUpdate — Unity Official Tutorials
Un po ‘ più di ricerca è emersa:
In conclusione, metti tutta la tua logica di gioco in Update o FixedUpdate. Non mescolare e abbinare timesteps a meno che non si è disposti a mordere il proiettile e accettare qualche balbuzie. Inoltre, vale la pena considerare di mettere tutto lo stato del gioco in FixedUpdate, utilizzando l’aggiornamento esclusivamente per l’input dell’utente, gli effetti visivi e l’interpolazione tra gli stati del gioco. Anche se questo richiede un cambiamento come strutturare i vostri giochi, si tratta di una struttura di design collaudato con molti vantaggi.
— KinematicSoup — Timesteps and Acheiving Smooth Motion in Unity
Un video clip in questo articolo illustra il problema di miscelazione e corrispondenza timesteps.
Prima di seguire questo consiglio ho voluto ricreare il problema di miscelazione e la congruenza timesteps mia.
La versione finale del progetto che ho usato per scrivere questo articolo è disponibile per il download.
Update Versus FixedUpdate
Dobbiamo iniziare con una comprensione di base della differenza tra i metodi Update e FixedUpdate. Per illustrare, creiamo un GameObject vuoto chiamato Setup e aggiungiamo il seguente componente di script:
Assets / Setup.cs (incompleto)
La nostra uscita console dopo 3 secondi sembrava:
Osservazioni:
- Aggiornamento viene chiamato prima di ogni rendering; la frequenza (frame rate) che varia in base alla complessità del rendering e il dispositivo host. I computer potenti possono raggiungere frame rate superiori a 150fps; il mio computer di sviluppo funzionava a circa 50fps. Al di sotto di 30 fps, è considerato una scarsa esperienza.
- FixedUpdate viene chiamato prima di ogni aggiornamento fisico interno (spostare le cose a causa della fisica, ad esempio la gravità). Il timestep fisso di Unity è impostato su 0.02; porta a FixedUpdate chiamato 50 volte al secondo.
Simulare Frame Rate lento
Al fine di simulare un frame rate lento (10fps), aggiorniamo la configurazione.script cs come segue:
Assets / Setup.cs (incompleto)
La nostra uscita console dopo 3 secondi sembrava:
Osservazioni:
- Impostazione vSyncCount a 0 disabilita l’Unità di sincronizzazione di rendering e di aggiornamento dello schermo tassi.
- Il frame rate effettivo può essere inferiore a
TARGET_FRAME_RATE
a causa delle limitazioni del dispositivo host e della complessità del rendering.
Animazione manuale
Per osservare l’effetto di varie animazioni, iniziamo posizionando un cubo fisso come riferimento.
We add our first animated GameObject (Sphere) in front of it with the following script component.
Assets/Sphere.cs (incomplete)
Running it with the normal frame rate:
Running it with 10fps frame rate:
Observations:
- Ovviamente, abbiamo un problema. Non vogliamo che la velocità di animazione dipenda dal frame rate.
- Il problema è perché stiamo impostando la VELOCITÀ su 0,1 unità / frame; vogliamo che la velocità sia misurata in unità / secondo.
La correzione è di fornire la VELOCITÀ nelle unità di unità / secondo; 0.1 unità / frame * 50 fotogrammi / secondo = 5 unità / secondo. Allora usiamo il Tempo.deltaTime per conoscere il tempo dall’ultima chiamata per l’aggiornamento. Quindi la distanza percorsa è VELOCITÀ * deltaTime.
Risorse / Sfera.cs (incompleto)
Con questa correzione in atto, otteniamo la stessa animazione indipendentemente dal frame rate (ma con 10fps, è a scatti come previsto).
dopo Aver utilizzato il frame rate ridotto per illustrare la necessità di fornire velocità in unità / in secondo luogo, possiamo commentare le righe nel programma di Installazione.cs che ha simulato un frame rate lento.
Animazione in fisica
Invece di animare manualmente un oggetto GameObject, possiamo animarlo applicando la fisica ad esso. Siamo in grado di animare un cilindro (lo spostamento a destra di 5 unità / secondo) da:
- Creazione di un Piano (denominato Piano)
- Creazione di un Cilindro (chiamato Cilindro)
- Aggiungere un Rigidbody componente Cilindro (e zero rotazione in tutte le direzioni)
- Creare una fisica del materiale, Scivoloso, senza attrito e applicare a Cilindro e Piano
- Inizia a Cilindro con una velocità iniziale utilizzando un componente di script
Attività/Cilindro.cs
Con questo posto, possiamo vedere che la sfera e il cilindro si muovono a destra alla stessa velocità.
Osservazioni:
- La Sfera posizione viene aggiornata immediatamente prima del render (manualmente nel metodo Update)
- Il Cilindro viene aggiornata la posizione interna di fisica di aggiornamento.
Animazione con Animazione
Un terzo modo di animare un oggetto GameObject è con un’animazione (ovviamente). Possiamo animare una capsula (tentando di muoversi a destra di 5 unità / secondo) da:
- Creando una capsula (chiamata Capsula)
- Creando un controller di animazione (anche Capsula) e aggiungendo come componente alla Capsula GameObject.
- Creazione di un’animazione (anche Capsula).
- Nel controller animazione creare uno stato (Start) con il suo movimento per essere l’animazione Capsula.
- Infine, animiamo la posizione in modo che la posizione orizzontale della capsula sia di 5 unità in 1 secondo.
Con questo posto, possiamo vedere che la sfera, il cilindro, la capsula (quasi) si muovono a destra alla stessa velocità.
Osservazioni:
- Non so perché, ma la Capsula spostato leggermente superiore al previsto; problemi girato per un po ‘ e non capire il perché.
- La posizione della Capsula può essere configurata per l’aggiornamento prima del rendering (default) o durante l’aggiornamento della fisica.
Implicazione di un frame Rate veloce
Su computer potenti, si può raggiungere frame rate fino a 150fps. Su questi computer con gli aggiornamenti di fisica predefiniti 50 volte al secondo (0,02 secondi tra gli aggiornamenti), gli elementi che vengono aggiornati prima di ogni rendering vengono aggiornati più frequentemente di quelli aggiornati negli aggiornamenti di fisica. Questa discrepanza è la fonte di problemi di miscelazione e corrispondenza timesteps.
Mentre non posso aumentare il frame rate della mia macchina di sviluppo (limitato a circa 50fps), posso rallentare artificialmente gli aggiornamenti fisici a 10 aggiornamenti al secondo (0.1 secondi tra gli aggiornamenti) utilizzando le impostazioni del progetto.
Come si può vedere, da miscelazione e la congruenza timesteps abbiamo ricreato il problema (incoerente movimento tra GameElements).
Per correggere, possiamo cambiare l’animazione della Capsula per aggiornare gli aggiornamenti sulla fisica, e allo stesso modo aggiornare il componente script della Sfera come segue:
Assets/Sphere.cs
Con questo, tutte le animazioni vengono costantemente aggiornate prima di ogni aggiornamento di fisica.
Infine, ci restituiscono la nostra fisica di aggiornamento per essere 50fps (o ogni 0.02 secondi); raggiungere sia il costante e puntuale aggiornamento.
Conclusioni
Avere, abbastanza facilmente, ricreato il problema di miscelazione e la congruenza timesteps, ho convinto me stesso che avrei dovuto mettere tutti stato del gioco in FixedUpdate metodi.