Differenza tra il metodo di aggiornamento e FixedUpdate in Unity?


14

sto iniziando a imparare Unity3d e una delle confusioni che ottengo è la differenza tra Update()e FixedUpdate().

Sto seguendo il tutorial di sviluppo del gioco Lynda Unity 2D lì, l'istruttore usa il Updatemetodo, il giocatore ha il componente RigidBody2D e il collider Box, usa il Updatemetodo per tradurre il giocatore, ma quando faccio lo stesso nel Updategiocatore non si muove ma quando lo faccio dentro FixedUpdate, tutto funziona. Sta dando tutorial da Unity 4.3 e sto seguendo il corso in Unity 4.6.

Dove dovrei usare Updatee FixedUpdate?

Risposte:


14

Stavo per scrivere questo come commento, ma alla fine è stato piuttosto prolisso, quindi l'ho trasformato in una risposta.

Le risposte attuali sono per lo più corrette, ma alcune cose menzionate sono fuorvianti / sbagliate.

In generale, entreranno in gioco la maggior parte delle attività legate al gioco Update.

Ad esempio, non si desidera eseguire il polling per l'input FixedUpdate(non a causa delle prestazioni, ma semplicemente perché le chiamate non funzionano correttamente). L'IA cade nella stessa barca.

La fisica costantemente aggiornata è l' unica attività correlata al gioco che FixedUpdatedovrebbe essere utilizzata. Chiamate non continue / occasionali a cose come Physics.Raycast, o addirittura Rigidbody.AddForceappartenenti Update. La mia menzione Rigidbody.AddForceè apparentemente contraria a ciò che potrebbe essere implicito nella documentazione, ma la chiave è Continuo vs Non continuo.

Una grande ragione per cui appartiene solo la fisica continua FixedUpdateè la natura reale di FixedUpdate. Altre risposte hanno menzionato il modo in cui FixedUpdate viene chiamato a un fisso interval, but that's slightly misleading. In reality, a script is passed a time in Time.deltaTime/ Time.fixedDeltaTime* che non corrisponde direttamente al tempo effettivo tra le chiamate, ma piuttosto al tempo simulato tra le chiamate.

(* Time.deltaTimee Time.fixedDeltaTimehanno lo stesso valore quando vengono chiamati in FixedUpdate[Unity è in grado di dire se la chiamata corrente ha Time.deltaTimeavuto origine durante FixedUpdatee ritorna Time.fixedDeltaTime])

Naturalmente lo stesso modo Updatenon può essere chiamato in modo costante a causa delle prestazioni variabili, né lo è FixedUpdate. La differenza chiave è che, ogni frame, se FixedUpdatenon è stato chiamato abbastanza spesso per fare una media dell'intervallo corretto tra le chiamate, viene chiamato più volte (o non viene chiamato la media è troppo alta). Questo è ciò a cui fanno riferimento i documenti sull'ordine di esecuzione dicendo che FixedUpdate può essere chiamato più volte un frame:

... FixedUpdate: FixedUpdate è spesso chiamato più frequentemente di Update. Può essere chiamato più volte per fotogramma, se la frequenza dei fotogrammi è bassa e potrebbe non essere chiamata tra i fotogrammi se la frequenza dei fotogrammi è alta ...

Ciò non influisce sulla fisica a causa della natura del resto dell'ordine di esecuzione e del motore, ma qualsiasi altra cosa inserita FixedUpdateverrà influenzata e causerà problemi.

Ad esempio, se si inserisce l'elaborazione AI all'interno, FixedUpdatenon c'è motivo di presumere che l'IA non salterà gli aggiornamenti per più frame di fila. Inoltre, ogni volta che `FixedUpdate rimane indietro, la tua IA si aggiornerà più volte in un singolo fotogramma prima che cose come la fisica e l'input / movimento del giocatore vengano elaborati, il che è almeno uno spreco di elaborazione, ma è anche estremamente probabile che causi duro per rintracciare bug e comportamenti irregolari.

Se è necessario eseguire un'operazione a intervalli fissi, utilizzare altri metodi forniti da Unity come Coroutinese InvokeRepeating.

E una piccola nota su Time.deltaTimee quando usarlo:

Il modo più semplice per descrivere l'effetto di Time.deltaTime è cambiare un numero da unità per frame a unità al secondo . Ad esempio, se si dispone di uno script con qualcosa di simile transform.Translate(Vector3.up * 5)ad Update, essenzialmente si sta spostando la trasformazione a una velocità di 5 metri per frame . Ciò significa che se il framerate è basso, il movimento è più lento e se il framerate è alto, il movimento è più veloce.

Se prendi lo stesso codice e lo cambi in transform.Translate(Vector3.up * 5 * Time.deltaTime), l'oggetto viene spostato a una velocità di 5 metri al secondo . Ciò significa che, indipendentemente dal framerate, l'oggetto si sposterà di 5 metri ogni secondo (ma più lento è il framerate, più il movimento dell'oggetto apparirà più fugace poiché si sposta sempre della stessa quantità ogni X secondi)

In generale, vuoi che il tuo movimento sia al secondo. In questo modo, indipendentemente dalla velocità a cui sta andando il computer, la tua fisica / movimento si comporteranno allo stesso modo e non avrai strani bug che si apriranno su dispositivi più lenti.

E non ha senso usarlo FixedUpdate. A causa di ciò che ho menzionato sopra, otterrai ogni volta lo stesso valore (il valore Timestep aggiornamento fisso) e non farà nulla ai tuoi valori. Il movimento / la fisica definiti in FixedUpdatesaranno già in unità al secondo, quindi non ne avrai bisogno.


4

La Updatefunzione si chiama ogni frame. La sua frequenza dipende dalla velocità con cui il computer è in grado di eseguire il rendering delle immagini. Su un computer più lento, Updateviene chiamato meno frequentemente rispetto a uno più veloce. Se si eseguono calcoli basati sul tempo, è possibile normalizzarli utilizzando ciò Time.deltaTimeche indica da quanto tempo Updateè stato chiamato dall'ultima volta (si applicano avvertenze).
In genere verrà utilizzato Updateper eseguire attività relative alla visualizzazione (ad es. Aggiornamento di un elemento dell'interfaccia utente)

La FixedUpdatefunzione viene chiamata a intervalli fissi. Indipendentemente dalla frequenza di aggiornamento dell'immagine, FixedUpdateverranno chiamati 1/Time.fixedDeltaTimevolte al secondo.
In genere verranno utilizzati FixedUpdateper eseguire attività correlate al gioco (ad es. Aggiornamento della fisica)


È un'alternativa alla moltiplicazione per il tempo Time.delta? C'è un motivo per usare l'uno o l'altro?
Ben

@Ben hanno due obiettivi diversi e dovresti usare la funzione corretta per quello che stai facendo.
o0 '.

@Lohoris Spiacente, intendevo dire che c'è un motivo per usare FixedUpdate su Update e moltiplicare le cose per Time.deltaTime per renderle indipendenti dal frame?
Ben

@Ben sì, precisione. In un sistema con rendering lento, Updateviene chiamato sempre meno spesso e la tua simulazione ne risentirà molto. Potresti non notare mentre la simulazione è semplice, ma si romperà facilmente in modo orribile quando non lo è.
o0 '.

1
@Ben no: se vuoi che la tua simulazione sia precisa, devi fare molti piccoli passi, non enormi ogni volta casualmente più grandi o più piccoli. E no, il punto centrale di FixedUpdate è che viene chiamato così tante volte, senza fare domande.
o0 '.

2

Da: http://unity3d.com/learn/tutorials/modules/beginner/scripting/update-and-fixedupdate

Il passo temporale utilizzato in FixedUpdate non è variabile.

Se il tuo gioco inizia a rallentare, quando raggiunge, non vuoi> 10 secondi di fisica in un aggiornamento, quindi in genere viene eseguito in FixedUpdate che viene chiamato a intervalli fissi.

Per esempio:

Update(float elapsedSeconds)
{
  Position += Velocity * 34.23423; //Windows Update is self-important
}
FixedUpdate(float elapsedSeconds)
{
  Position += Velocity * 0.0166; //60fps
}

Dove:

Update(34.23423)

==

FixedUpdate(10.0)
FixedUpdate(10.0)
FixedUpdate(10.0)
//4.23423 + 5.76577 game-seconds later...
FixedUpdate(10.0)

L'ho menzionato nella mia risposta, ma in FixedUpdaterealtà non viene chiamato a un intervallo fisso. La vera natura di FixedUpdateè comprimere più cicli della fisica in un fotogramma se il gioco inizia a rallentare e saltare i cicli se sta andando troppo veloce in modo che la media raggiunga il Timestep di aggiornamento fisso. Unity non è multi-thread, quindi non ci sarebbe modo di garantire chiamate FixedUpdate a intervalli fissi (cosa succede quando un FixedUpdate impiega troppo tempo). Anche se lo fosse, probabilmente sarebbe ancora quasi impossibile.
Selali Adobor,

La maggior parte delle persone [Unity?] Non sono consapevoli del fatto che Render / Update / FixedUpdate sono tutti richiamati all'interno di un singolo metodo di callback, quindi ho concettualizzato. Grazie per i tuoi sforzi!
Jon,

2

Updateviene chiamato il più velocemente possibile. La variabile "Time.deltaTime" è impostata sul tempo effettivo trascorso dall'ultima chiamata. Se il ritardo o qualcosa di simile rallenta il gioco, Updateverrà comunque chiamato solo una volta al termine del ritardo, con un valore elevato di deltaTime.

FixedUpdateviene chiamato a intervalli regolari. Non verrà mai chiamato più spesso del rapporto specificato in "Time.fixedDeltaTime". Se il ritardo o qualcosa di simile rallenta il gioco, FixedUpdateverrà chiamato più volte in rapida successione per consentire al gioco di recuperare. Time.deltaTimeè impostato uguale a Time.fixedDeltaTimeprima che FixedUpdatevenga eseguito, ma questo è solo un problema per facilitare la migrazione del codice tra i due.

Generalmente, Updatedovrebbe essere usato per comportamenti interpolabili e FixedUpdateper comportamenti che devono essere calcolati passo dopo passo, o che dipendono da quelli che lo fanno, come il movimento basato sulla fisica. Se stai scrivendo qualsiasi tipo di loop Updatelungo le righe per for(time=0;time<=deltaTime;time+=someStep)...allora probabilmente dovresti farlo in FixedUpdate.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.