2012-08-12 11 views
7

Quindi volevo convertire il mio gioco per PC per funzionare su Xbox 360. Funzionava dannatamente bene sul PC, con un Intel Core 2 Quad @ 2.40Ghz e un Radeon 4850 512MB.PC XNA Game convertito in Xbox 360 - Enormi problemi di prestazioni

L'ho portato su Xbox e, a prima vista, c'era qualche problema con l'invarianza e l'ereditarietà per quanto riguarda l'importazione di liste, quindi ho semplicemente usato il metodo LINQ chiamato .Cast <>().

Se questo metodo è prende un grosso in testa, me lo faccia sapere, perché io non posso schierare analisi delle prestazioni sulla 360 per qualche motivo, molto probabilmente perché gioca sulla 360.

Poi un altro problema è venuto, ed è era un bel System.OutOfMemoryException. Le mie textures skybox erano 4096x4096, quindi la loro rimozione rimosse per metà quell'errore. Strano però, erano solo 3MB x 6, quindi non dovrebbe usare quella parte dei 512 MB disponibili.

Quindi, quando tutti questi problemi sono stati risolti, è stato introdotto un bel frame per 2 secondi. Quindi si blocca dopo 1 minuto di gioco, un "codice 4" qualunque cosa significhi.

Suona come un powerpoint. Ecco alcune immagini di analisi delle prestazioni dal gameplay del PC. Non sono male.

CPU: http://i.imgur.com/JYx7Z.png RAM: http://i.imgur.com/C29KN.png E 72% = 150 MB attenzione.

Spero che qualcuno qui abbia qualche esperienza in merito a questo problema. Francamente sono tutto orecchie.

risposta

11

La causa principale dei problemi di prestazioni è quasi certamente perché si sta allocando memoria mentre il gioco è in esecuzione (dopo l'avvio, durante il ciclo Draw/Update).

Su Windows questo va bene. Il garbage collector su Windows è generazionale (pulirà solo i nuovi oggetti quando possibile) ed estremamente veloce. È intelligente quando sceglie di correre anche lui.

Il garbage collector su Xbox 360, d'altra parte, è completamente spazzatura. Funziona per ogni 1 MB di memoria allocata. Controlla l'intero heap gestito quando viene eseguito. Ed è piuttosto lento da avviare.

Quindi la risposta è di non allocare mai memoria mentre il gioco è in esecuzione.

C'è un buon post sul blog su questo here. (Esso descrive anche l'alternativa di non allocare la memoria -, che è quello di ridurre la complessità heap - che è davvero molto difficile da attuare e non lo consiglio.)

  • Sarà necessario rimuovere le cose come LINQ, come gli oggetti query che crea sono oggetti heap, così come i delegati che richiede frequentemente. Usa invece dei loop semplici.
  • Se si assegnano i propri tipi di riferimento in draw/update, sarà necessario convertirsi all'utilizzo di tipi di valore laddove possibile o aggiungere il pool di oggetti.
  • La creazione di oggetti string è un'altra fonte comune di allocazioni di memoria, invece è possibile riutilizzare uno StringBuilder e renderlo direttamente.
  • La conversione di elementi (in particolare: numeri) in stringhe, anche per StringBuilder allocherà memoria. È necessario scrivere/trovare alternative prive di allocazione.My answer to this similar question ha uno per int.

Il modo migliore per diagnosticare in cui si assegnano la memoria è quello di eseguire il gioco con il CLR Profiler su Windows. Questo ti dirà dove e quando verrà assegnata la memoria. Ottimizza semplicemente fino a quando non stai assegnando.

(O fino a quando non si assegna in modo affidabile meno di 1 MB per livello/mappa/sala/altro, e si esegue un GC manuale in un momento in cui è opportuno rallentare, come uno schermo di caricamento statico o una dissolvenza da nero a nero .)

Codice 4 è un'eccezione non gestita. È necessario installare un gestore di eccezioni di primo livello che emetta un messaggio o esegua il gioco nel debugger per determinarne la causa.

Infine: questa è probabilmente la compressa delle dimensioni delle trame (utilizzando PNG o JPEG o simile). Se le trame non sono compresse, 4096 × 4096 × 6 × 4 byte = 384 MB. Questo è enorme - non c'è da meravigliarsi se hai esaurito la memoria. Potresti comprimerli con DXT1 e renderli 6 volte più piccoli (instructions, wiki). Potresti anche ridurre la loro risoluzione. E ti serve la faccia inferiore?

+1

Grazie mille, dopo molte ricerche ho trovato una risposta simile alla tua e quando ho eseguito il mio profilo CLR ho scoperto che stavo allocando circa 60 MB per frame ... non va bene. È perché aggiungo tutti gli oggetti collidabili nel mio gioco a un elenco, quindi li inserisco in un Collision Thread ogni frame. Potrei farne una lista statica, dove è solo un riferimento, che probabilmente farò, ma poi ho la possibilità di un collision lag. Ma immagino sia l'unica opzione. –