Domanda

  1. Chiamata sceneggiatura main.lua ad ogni gioco iterazione del ciclo - è buono o cattivo design? Come influisce sulle prestazioni (relativamente)? ??

  2. mantenere lo stato di gioco da a . C ++ host-programma o b . da script Lua o c . da entrambi e sincronizzare loro?

(domanda precedente sul tema: Lua e C ++: separazione dei compiti )

(Io voto per ogni risposta. La risposta migliore sarà accettata.)

È stato utile?

Soluzione

La cosa migliore di lua è che ha una VM leggero, e dopo i pezzi vengono precompilati loro esecuzione nella macchina virtuale è in realtà abbastanza veloce, ma ancora non così rapidamente come un codice C ++ sarebbe, e non credo chiamando lua ogni fotogramma reso sarebbe una buona idea.

ci metto lo stato del gioco in C ++, e aggiungi funzioni in lua che possono raggiungere, e modificare lo stato. Un approccio basato su eventi è quasi meglio, dove la registrazione evento deve essere fatto in lua (preferibilmente solo all'inizio del gioco o in occasione di eventi di gioco specifici, ma non più di un paio di volte al minuto), ma gli eventi effettivi dovrebbe essere licenziato da codice C ++. input dell'utente sono eventi troppo, e di solito non accadono ogni frame (tranne forse MouseMove, ma che devono essere usati con cautela a causa di questo). Il modo di gestire eventi di input utente (se si gestisce tutto (come che è stato premuto il tasto, ecc) in lua, o se ci sono per esempio eventi separati per ciascuna tasti della tastiera (in un caso estremo) dipende dal gioco che si' re cercando di fare (un gioco a turni potrebbe avere solo un gestore di eventi per tutti gli eventi, un RTS dovrebbero avere più eventi, e un FPS dovrebbero essere trattati con cautela (soprattutto perché spostando il mouse accadrà ogni fotogramma)). in genere, la più tipi distinti di eventi che hai, meno si devono il codice a lua (che consentirà di aumentare le prestazioni), ma il più difficile si arriva se un "vero e proprio evento" è necessario manico è in realtà innescato da più separati "programmazione eventi di livello" ( che potrebbe effettivamente ridurre le prestazioni, perché le esigenze di codice lua di essere più complessa).

In alternativa, se la prestazione è davvero importante che si può effettivamente migliorare la lua VM con l'aggiunta di nuovi codici operativi ad esso (ho visto alcune delle aziende per fare questo, ma soprattutto per rendere la decompilazione dei pezzi LUA compilati più difficile), che non è in realtà una cosa difficile da fare. Se avete qualcosa che le esigenze di codice lua da fare un sacco di volte (come evento registrazione, eventi in esecuzione, o cambiare lo stato del gioco) si potrebbe desiderare di attuarle nel lua VM, così invece di molteplici getglobal e setglobal codici operativi avrebbero preso solo uno o due (per esempio, si potrebbe fare un'opcode setstate con 0-255 e un parametro 0-65535, dove i primi descibes parametri quali stato di modificare, e la seconda desribes il nuovo valore dello stato. di Naturalmente questo funziona solo se si dispone di un massimo di 255 eventi, con un massimo di 2 ^ 16 valori, ma potrebbe essere sufficiente in alcuni casi. E il fatto che questo richiede solo un mezzo di codice operativo che il codice verrà eseguito più velocemente). Ciò consentirebbe anche di rendere più difficile la decompilazione se avete intenzione di oscurare il proprio codice lua (anche se non molto a qualcuno che conosce il funzionamento interno di Lua). Esecuzione di alcuni codici operativi per fotogramma (circa 30-40 cime) non colpiranno le vostre prestazioni così male. Ma 30-40 codici operativi nel lua VM non ti porterà lontano se avete bisogno di fare cose veramente complesse (un semplice if-then-else può richiedere fino a 10-20 o più codici operativi a seconda della espressione).

Altri suggerimenti

La mia regola di base per Lua è - o in qualsiasi linguaggio di script in un gioco -

  • Tutto ciò che accade su ogni fotogramma: c ++
  • eventi asincroni - input dell'utente - lua
  • sincroni eventi motore di gioco - lua

In sostanza, questo è alcun codice chiamato a> 33-100Hz (a seconda della frequenza) è C ++ Provo a richiamare il motore di script <10Hz.

In base a qualsiasi tipo di metrica attuale? non proprio. ma mette una linea che divide nel disegno, con c ++ e compiti lua chiaramente definiti - colpo sopra delineazione fronte i per frame compiti lua crescerà finché non vengono bogging elaborazione per frame - e quindi non c'è nessun orientamento chiaro su cosa prune.

Sto usando Lua per la prima volta in un gioco che ho lavorato su. Il lato C ++ della mia applicazione in realtà contiene dei puntatori alle istanze di ogni stato del gioco. Alcuni degli stati di gioco sono implementate in C ++ e alcuni sono implementate in Lua (come ad esempio lo stato "di gioco").

L'aggiornamento e ciclo principale applicazione diretta sul lato C ++ delle cose. Ho esposto le funzioni che permettono al Lua VM per aggiungere nuovi stati di gioco per l'applicazione in fase di esecuzione.

Non ho ancora avuto problemi con lentezza, anche in esecuzione su hardware con risorse limitate (processore Atom con video integrato). funzioni Lua sono chiamati ogni frame . L'operazione più costosa (in termini di tempo) nella mia domanda è di rendering .

La possibilità di creare completamente nuovi stati in Lua è stata una delle migliori decisioni che ho preso al progetto, in quanto mi permette di aggiungere liberamente porzioni di gioco senza dover ricompilare il tutto.

Edit: sto usando Luabind , che ho letto esegue più lento in generale rispetto altri quadri vincolanti e naturalmente API Lua C.

non mi piace C ++. Ma mi piacciono i giochi.

Il mio approccio potrebbe essere un po 'atipico: io faccio tutto quello che posso in Lua, e solo il minimo assoluto in C ++. Il ciclo di gioco, le entità, ecc sono tutti fatti in Lua. Ho anche un'implementazione quadtree fatto in Lua. ++ maniglie C grafica e roba del file system, nonché l'interfacciamento con librerie esterne.

Questa non è una decisione basata sulla macchina, ma un programmatore a base di uno; codice di uscita di gran lunga più veloce in Lua che in C ++. Così passo i miei cicli programmatore sulle nuove funzionalità piuttosto che sul risparmio cicli di computer. Le mie macchine di destinazione (qualsiasi laptop degli ultimi 3 anni) sono in grado di far fronte a questa quantità di Lua molto facilmente.

Lua è sorprendentemente basso-footprint (date un'occhiata alla luaJIT se non lo si conosce).

Detto questo, se mai a trovare un collo di bottiglia (non ho ancora) io Profilo L'gioco al fine di trovare la parte lenta, e io traduco quella parte di C ++ ... solo se posso' t trovare un modo intorno ad esso utilizzando Lua.

  1. Probabilmente non si desidera eseguire l'intero script Lua su ogni fotogramma iterazione, perché ogni gioco sufficientemente complesso avrà più oggetti di gioco con i propri comportamenti. In altre parole, i vantaggi di Lua sono perso a meno che non si dispone di più script molto piccoli che gestiscono una parte specifica del comportamento di un gioco più grande. È possibile utilizzare la funzione lua_call di chiamare qualsiasi routine lua appropriata nello script, non solo l'intero file.

  2. Non c'è risposta ideale qui, ma la stragrande maggioranza del vostro stato di gioco è tradizionalmente memorizzata nel motore di gioco (cioè C ++). Si rivelano a Lua Lua appena sufficiente per fare il processo decisionale che avete assegnato a Lua.

È necessario considerare che il linguaggio è appropriato per la quale i comportamenti. Lua è utile per i controlli di alto livello e le decisioni, e C ++ è utile per il codice orientato alla prestazione. Lua è particolarmente utile per le parti del gioco che è necessario modificare senza ricompilare. Tutte le costanti e le variabili magiche potrebbe andare in Lua, per esempio. Non cercare di calzascarpe Lua in cui non appartiene, vale a dire grafica o rendering audio.

script IMHO Lua sono per specifici comportamenti, è sicuramente andando a influire negativamente sulle prestazioni se si chiama uno script Lua 60 volte al secondo.

script Lua sono spesso roba separata come comportamento, e gli eventi specifici e la logica Game Engine (GUI, Posta, finestre di dialogo, gli eventi del motore di gioco, ecc ...). Un uso bene di Lua per esempio potrebbe essere quando innescando un'esplosione (particella FX), se il gioco Character cammina da qualche parte, hard-codifica l'output di tale evento nel tuo motore sarebbe una scelta molto brutto. Anche se, facendo il grilletto del motore lo script corretta sarebbe una scelta migliore, disaccoppiamento che il comportamento specifico il vostro motore.

mi sento di raccomandare, per cercare di mantenere il vostro State Game in una parte, invece di upscaling il livello di complessità di stati che mantengono sincronizzate in due punti (Lua e motore), aggiungere filettatura a questo, e si finirà per avere un molto brutto pasticcio. Keep it simple. (Nei miei disegni Io per lo tengo lo Stato del Gioco in C ++)

Buona fortuna con il vostro gioco!

Circa le prestazioni di 1:. Se main.lua non cambia, caricarlo una volta con lua_loadfile o loadfile, Salva un riferimento alla funzione restituita, e quindi chiamare quando necessario

La maggior parte delle prestazioni sarà persa attraverso il legame tra il Lua e C ++. Una chiamata di funzione effettivamente deve essere avvolto, e ri-avvolto, e così un paio di tempo normalmente. codice puro Lua o puro C ++ è di solito più veloce di codice misto (per le piccole operazioni).

Detto questo, io personalmente non ho visto alcun forte prestazioni HIT esecuzione di uno script Lua ogni frame .

Di solito scripting è bravo a alto livello . Lua è stato utilizzato in giochi famosi per il Motori di ricerca ( Quake 3 ) e per la Interfaccia utente ( World of Warcraft ). Usato ad alto livello Lua micro-discussioni tornare utile: I co-routine possono risparmiare un sacco (rispetto a discussioni reali). Ad esempio, per eseguire del codice Lua solo una volta ogni tanto.

Mi piacerebbe gettare i miei due centesimi poiché credo fermamente che ci sia qualche consiglio errato qui viene data. Per contesto, sto usando Lua in un grande gioco che coinvolge sia il rendering 3D ad alta intensità, così come la simulazione logica di gioco intenso. Sono diventato più familiare di quanto mi sarebbe piaciuto con Lua e le prestazioni ...

Si noti che ho intenzione di parlare in modo specifico LuaJIT, perché si sta andando a voler utilizzare LuaJIT. E 'plug-and-play, davvero, quindi se è possibile incorporare Lua è possibile incorporare LuaJIT. Avrai voglia di esso, se non per la velocità in più, poi per il modulo di interfaccia funzione estera automagic (require 'FFI') che vi permetterà di chiamare il codice nativo direttamente da Lua senza mai dover toccare l'API Lua C (95 % + dei casi).

  1. E ' perfettamente bene per chiamare Lua a 60Hz (io lo chiamo a 90Hz in VR ..). Il problema è che si sta andando ad avere per essere attenti a farlo correttamente. Come qualcun altro ha detto, è fondamentale che si caricare lo script solo una volta . È quindi possibile utilizzare l'API C per ottenere l'accesso alle funzioni definite in quello script, o per eseguire lo script in sé come una funzione. Vi consiglio l'ex: per un tempo relativamente semplice gioco, è possibile cavarsela con la definizione di funzioni come onUpdate (dt), onRender (), onKeyPressed (chiave), onMouseMoved (dx, dy), ecc È possibile chiamare questi al momento opportuno dal ciclo principale in C ++. In alternativa, si può effettivamente avere l'intero ciclo principale sia in Lua, e invece invocare il codice C ++ per le routine di performance-critical (lo faccio). Ciò è particolarmente facile da fare con la LuaJIT FFI.

  2. Questa è la domanda davvero difficile. Dipenderà dalle vostre esigenze. Riesci a martello giù abbastanza facilmente lo stato del gioco? Grande, metterlo C ++ - lato e l'accesso da LuaJIT FFI. Non so cosa sarà in stato di gioco / come essere in grado di realizzare prototipi in fretta? Niente di male tenendolo in Lua. Cioè, fino a quando si inizia a parlare di un gioco complesso con 1000s di oggetti, ciascuno stato non banale contenente. In questo caso, ibrida è la strada da percorrere, ma capire esattamente come dividere lo stato tra C ++ e Lua, e come marziale ha dichiarato lo stato tra i due (soprattutto nelle routine di Potenza-critical) è qualcosa di un'arte. Fatemi sapere se si arriva con una tecnica a prova di proiettile :) Come per tutto il resto, la regola generale è: dati che passano su percorsi esigenze di prestazioni critiche per essere sul lato nativo. Ad esempio, se i soggetti hanno posizioni e le velocità che si aggiorna ogni fotogramma, e si dispone di migliaia di dette entità, è necessario fare questo in C ++. Tuttavia, è possibile ottenere via con la stratificazione di un 'inventario' in cima a questi soggetti che utilizzano Lua (un inventario non ha bisogno di un aggiornamento per-frame).

Ora, un altro paio di note che vorrei buttare fuori sia come FYIs generale e in risposta ad alcune delle altre risposte.

  1. approcci Event-based sono, in generale, fondamentale per le prestazioni di qualsiasi gioco, ma che va doppiamente per i sistemi scritti in LUA. Ho detto che è perfettamente bene di chiamare Lua @ 60hz. Ma è non perfettamente bene di essere in esecuzione cicli stretti su un sacco di gioco di oggetti ogni fotogramma in detta Lua. Si potrebbe ottenere via con dispendiosamente chiamando update () su tutto l'universo in C ++ (anche se non si dovrebbe), ma in questo modo in Lua si iniziare a mangiare quei preziosi millesimi di secondo troppo in fretta. Invece, come altri hanno detto, è necessario pensare di logica Lua come 'reattivo' - Di solito, questo movimentazione un evento mezzi. Ad esempio, non controlla che un'entità è nel raggio di un altro ogni fotogramma in Lua (voglio dire, questo è bene per una sola entità, ma in generale quando si è scaling up il vostro gioco è necessario non pensare come questo). Invece, informi il motore di C ++ per informare l'utente quando le due entità ottenere entro una certa distanza l'uno dall'altro. In questo modo, Lua diventa il controllore alto livello di logica del gioco, invio comandi ad alto livello e rispondere alleeventi di alto livello, non provveda alla routine di basso livello per la matematica della logica del gioco banale.

  2. Diffidate dei consigli che 'codice misto' è lento. L'API Lua C è leggero e veloce. funzioni di avvolgimento per l'uso con Lua è, nel peggiore dei casi, abbastanza facile (e se si prende un po 'per capire come le interfacce Lua con C WRT lo stack virtuale, ecc, si noterà che è stato progettato appositamente per ridurre al minimo chiamata in testa), e nel migliore dei casi, banale (senza avvolgimento richiesto) e il 100% come performante chiamate native (grazie, LuaJIT FFI!) nella maggior parte dei casi trovo che un'attenta miscela di Lua e C (attraverso il LJ FFI) è superiore alla pura Lua. Anche le operazioni di vettore, che credo i manuali LuaJIT parlare da qualche parte come un esempio in cui il codice deve essere tenuto a Lua, che ho trovato per essere più veloce quando eseguo attraverso chiamate lua-> C. In ultima analisi, fare chiunque non la fiducia o nulla, ma le vostre proprie misure (attenzione) di prestazioni quando si tratta di pezzi di codice che sono sensibili alle prestazioni.

  3. La maggior parte dei giochi di piccola-ish potevano farla franca bene con stato del gioco, il ciclo di base, la gestione di input, ecc fatto interamente in Lua e funzionante sotto LuaJIT. Se si sta costruendo un piccolo-ish gioco, prendere in considerazione il "passaggio a C ++, se necessario" approccio (compilation pigro!) Scrivere in Lua, quando si identifica un collo di bottiglia chiaro ( e hanno misurato per assicurarsi che sia il colpevole ), mossa che punta a C ++ e essere sulla buona strada. Se si scrive un grande gioco con 1000s di oggetti complessi con logica complessa, rendering avanzato, ecc allora sarà possibile usufruire della più up-front progettazione.

Buona fortuna:)

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top