Quali di questi due codici sono "migliori"? Fare una variabile locale o una variabile di classe?


11

Sto facendo più giochi e faccio domande più stupide.

Spero che questo sia molto breve. Sto creando una classe molto semplice che sposta semplicemente un oggetto Player applicando forza a un corpo rigido, ma mi ha fatto meravigliare, dovrei fare un riferimento di classe all'rb o solo una variabile locale all'interno di Aggiorna ogni frame? (tenendo presente che esiste già nella classe genitore Unità Monobehaviour.GameObject).

Mi chiedo se fare molte variabili locali rallenterebbe il ciclo nel suo insieme (per locale intendo all'interno della funzione stessa e non ai vertici della classe - spero di usare il termine corretto).

Ecco cosa intendo, i due modi in cui stavo pensando di farlo:

public class Player : MonoBehaviour {

private void FixedUpdate()
{
    Rigidbody rb = GetComponent<Rigidbody>();

    float v = Input.GetAxis("Vertical");

    rb.AddForce(v * rb.transform.forward * Const.walkForce);
}
}

o...

public class Player : MonoBehaviour {
Rigidbody rb;

private void Awake()
{
    rb = GetComponent<Rigidbody>();
}

private void FixedUpdate()
{
    float v = Input.GetAxis("Vertical");

    rb.AddForce(v * rb.transform.forward * Const.walkForce);
}
}

4
Sembra più una domanda per la revisione del codice SE.
Orphevs,

1
Puoi anche creare proprietà di classe float va.
Chad,

Probabilmente alla fine lo farò in realtà Chad, perché lo userò in due metodi all'interno della classe. Era davvero solo un semplice codice per far passare la domanda sulle variabili locali vs class senza gonfiarlo con un sacco di codice. Mi piace davvero mantenere le variabili locali (e "fuori mano" come dove!), Ma ovviamente devo assicurarmi di non iniziare a duplicare le cose invece di avere una variabile di classe per ognuna.
Big T Larrity,

Uno snippet di codice non è "un codice". Chiedere "quale codice è meglio" ti fa sembrare un dilettante.
Miles Rout,

1
sono un dilettante quindi va bene con me grazie Miles
Big T Larrity,

Risposte:


25

In generale, ho scoperto che dovresti esaminare i dati nel modo più stretto possibile per iniziare e ampliare l'ambito come scopri che è necessario. Ciò significa che se puoi renderlo una variabile locale anziché un membro, probabilmente dovresti iniziare da lì.

Questo perché un ambito più ristretto riduce il numero di posizioni nel codice in cui è necessario ragionare su tali dati e quindi riduce il numero di posizioni che è possibile ragionare in modo errato (il che porta a bug).

Dichiarare effettivamente le variabili locali da sole non sarà mai una preoccupazione per le prestazioni: sono economiche e i compilatori moderni possono persino ottimizzare gli "extra".

Inizializzarli può essere una preoccupazione; nel tuo caso il tuo corpo rigido viene controllato ogni volta tramite GetComponent, che ha un costo diverso da zero. Se sai che il componente del corpo rigido non cambierà per questo particolare oggetto di gioco, puoi cercarlo una volta e memorizzare il risultato in una variabile membro ed evitare un piccolo overhead per chiamata.

È improbabile che l'overhead per chiamata sarà significativo in questo caso, ma col tempo questo potrebbe sommarsi per molti componenti. Vorresti applicare un profiler per essere sicuro.

Quindi, per riassumere: in generale, per impostazione predefinita rendere le cose il più locali possibile, ma in questo caso è probabilmente ragionevole fare rbun membro in modo da poter eseguire la ricerca una volta dentro Awakeed evitare di doverlo fare ogni FixedUpdatechiamata.


1
grazie Josh, ho pensato che sarebbe stato meglio inizializzare l'rb solo una volta, e grazie mille per aver spiegato chiaramente il perché. È bello sapere con certezza, vedi che non ero sicuro al 100% che GetComponent contasse come inizializzandolo ogni volta, o semplicemente "guardandolo" dal comportamento mono. Ma ora ho ricevuto molte grazie per la risposta super rapida
Big T Larrity,

1
@SuperMegaBroBro GetComponent è piuttosto veloce - ti farebbe fatica a fare qualsiasi tipo di ricerca con una velocità comparabile. A meno che non si disponga di dati sulle prestazioni che suggeriscano che si tratta di un problema, attenersi all'approccio "mantieni le cose locali". Puoi sempre ottimizzarlo in seguito. Vedi answer.unity.com/questions/185164/… Non dimenticare che neanche la memorizzazione nella cache è gratuita: se memorizzi GetComponentnella cache ogni singolo gioco, probabilmente sarà una perdita netta. Misurare. Identifica dove valgono le ottimizzazioni. Concentrati sulla realizzazione di un grande gioco :)
Luaan,

1
L'essenza principale che dovresti togliere da questa risposta (che è abbastanza buona) è: Se vuoi cercare un codice su cui è più facile ragionare, testare e assicurarti che sia privo di bug, prendi la variabile locale. Ma, come sempre, a volte abbiamo bisogno di fare sacrifici per perfezionare il codice per motivi di prestazioni, quindi un membro della classe potrebbe essere appropriato (ma profilo prima, non fare semplicemente l'ottimizzazione prematura).
Polygnome,

grazie mille ragazzi, in particolare Luaan mentre mi chiedevo quel problema di "cache" mentre scrivevo la domanda originale (ma non sapevo davvero come esprimerlo). Adotterò sicuramente l'approccio "locale" il più possibile. grazie per tutto il grande aiuto come al solito ragazzi.
Big T Larrity,

2

La risposta di Josh Petrie è molto buona: ecco una prospettiva complementare.

Quando si lavora con codice di cui si capisce abbastanza bene il dominio, è possibile oscillare le variabili nel punto in cui hanno senso.

Ad esempio, se ho una Personclasse con un waveGoodbyemetodo, è possibile che la mia classe non avesse un handoggetto prima e quindi potrei dichiararlo localmente waveGoodbye. Ora qui è ovvio che una persona ha una mano, quindi potresti dichiararla naturalmente come membro Personsenza pensarci, ma si applica lo stesso problema.

Se dichiari handlocalmente, in seguito potresti aggiungere un karateChopmetodo che richiede anche una mano. Questo è quando dichiarare le variabili localmente può diventare problematico - perché gli sviluppatori junior spesso ricorrono a copiare / incollare la dichiarazione da waveGoodbyee ora hai lo stesso concetto situato in due punti. Eventuali modifiche devono handquindi essere modificate in entrambi i punti e quindi inizia una collina di formiche .

Quindi tutto sommato,

  1. Se sei sicuro del posizionamento della tua dichiarazione, cercala dove ha senso.

  2. Se non sei sicuro, avvia localmente e assicurati di eseguire il refactoring quando ottieni un soffio di riutilizzo del codice.

Modifica: Oh, e non fare lo stesso errore che ho di passare troppo tempo a capire dove intendere le tue dichiarazioni. È difficile comprendere la struttura dei tuoi dati in anticipo e mentre scrivi il tuo codice la struttura ha un modo di rivelarsi.


2
Pur avendo le cose naturalmente ordinata, come ogni Persondovrebbe avere il membro hand se rilevanti nell'applicazione, spesso aiuta altri sviluppatori (il più delle volte vi 6 mesi più tardi) per capire meglio il codice. In questo caso, sembra logico avere un Rigidbodymembro come tuo Playere, dico di più, anche se ciò implica prestazioni peggiori. Nei videogiochi questo è un punto rilevante da considerare, ma penso nel codice , essere chiari è spesso più importante
se l'

1
risposte eccellenti grazie ragazzi. Non sto provando a sembrare un know-all, ma tutte queste risposte hanno appena riaffermato quello che stavo già pensando, quindi per una volta sono molto felice e sto facendo dei bei progressi nei miei giochi. In questo momento sto realizzando un gioco di calcio in 3D con animazioni adeguate e tutto, facendo passi da gigante: D presto sarò qui per avere bisogno di aiuto su come renderlo a 2 giocatori e oserei dire mulitplayer online: D divertiti ragazzi e grazie ancora!
Big T Larrity,
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.