Lequel de ces deux codes est «meilleur»? Faire une variable locale ou une variable de classe?

11

Je fais plus de jeux et pose des questions plus stupides.

J'espère que celui-ci est très bref. Je crée une classe très basique qui déplace simplement un objet Player en appliquant une force à un corps rigide, mais je me suis demandé, devrais-je faire une référence de classe au rb ou juste une variable locale dans Mettre à jour chaque image? (en gardant à l'esprit qu'il existe déjà dans la classe parent d'unité Monobehaviour.GameObject).

Je me demande si faire de nombreuses variables locales ralentirait la boucle dans son ensemble (par local, je veux dire à l'intérieur de la fonction elle-même et non au sommet de la classe - j'espère utiliser le terme correct).

Voici ce que je veux dire, les deux façons dont je pensais le faire:

public class Player : MonoBehaviour {

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

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

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

ou...

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);
}
}
Big T Larrity
la source
4
Cela ressemble plus à une question pour la révision de code SE.
Orphevs
1
Vous pouvez également créer une propriété de classe va float.
Chad
Je finirai probablement en fait par Chad, car je vais l'utiliser dans deux méthodes au sein de la classe. C'était vraiment du code simple pour poser la question sur les variables locales vs de classe sans les gonfler avec beaucoup de code. J'aime vraiment garder les variables locales (et «à l'écart» comme où!) Mais bien sûr, je dois m'assurer de ne pas commencer à dupliquer les choses au lieu d'avoir une variable de classe pour chacune.
Big T Larrity
Un extrait de code n'est pas «un code». Demander `` quel code est le meilleur '' vous fait ressembler à un amateur.
Miles Rout
1
je suis un amateur donc c'est très bien avec moi merci Miles
Big T Larrity

Réponses:

25

En général, j'ai constaté que vous devez étendre les données aussi étroitement que possible pour commencer et élargir l'étendue selon vos besoins. Cela signifie que si vous pouvez en faire une variable locale au lieu d'un membre, vous devriez probablement commencer par là.

En effet, une portée plus étroite réduit le nombre d'emplacements dans le code où vous devez raisonner sur ces données, et réduit ainsi le nombre d'emplacements que vous pouvez raisonner incorrectement (ce qui conduit à des bogues).

En fait, déclarer des variables locales seules ne sera jamais pratiquement un problème de performances: elles sont bon marché et les compilateurs modernes peuvent même optimiser les "extras".

Leur initialisation peut être un problème; dans votre cas, votre corps rigide est recherché à chaque fois via GetComponent, ce qui a un coût non nul. Si vous savez que le composant de corps rigide ne changera pas pour cet objet de jeu particulier, vous pouvez le rechercher une fois et stocker le résultat dans une variable de membre et éviter une petite surcharge par appel.

Il est peu probable que la surcharge par appel soit importante dans cette seule instance, mais au fil du temps, cette opération pour de nombreux composants peut s'additionner. Vous voudriez appliquer un profileur pour être sûr.

Donc, pour résumer: en général, par défaut pour rendre les choses aussi locales que possible, mais dans ce cas, il est probablement raisonnable de créer rbun membre afin que vous puissiez effectuer la recherche une fois Awakeet éviter d'avoir à le faire à chaque FixedUpdateappel.


la source
1
merci Josh, je pensais que ce serait mieux d'avoir initialisé le rb une seule fois, et merci beaucoup d'avoir expliqué clairement pourquoi. Il est bon de savoir avec certitude, vous voyez, je n'étais pas sûr à 100% que le GetComponent comptait comme l'initialisation à chaque fois, ou simplement «en le recherchant» depuis le Monobehaviour. Mais maintenant, je reçois tellement de mercis pour la réponse utile super rapide
Big T Larrity
1
@SuperMegaBroBro GetComponent est assez rapide - vous auriez du mal à faire tout type de recherche ayant une vitesse comparable. À moins que vous ne disposiez de données sur les performances qui suggèrent qu'il s'agit d'un problème, respectez l'approche «garder les choses locales». Vous pouvez toujours l'optimiser ultérieurement. Voir answers.unity.com/questions/185164/… N'oubliez pas que la mise en cache n'est pas non plus gratuite - si vous mettez en cache chaque élément GetComponentde votre jeu, ce sera probablement une perte nette. Mesure. Identifiez où les optimisations en valent la peine. Concentrez-vous sur la création d'un grand jeu :)
Luaan
1
L'essentiel à retenir de cette réponse (ce qui est plutôt bien) est le suivant: si vous voulez rechercher le code le plus facile à raisonner, à tester et à vous assurer qu'il est exempt de bogues, prenez la variable locale. Mais, comme toujours, nous devons parfois faire des sacrifices pour perfectionner le code pour des raisons de performances, donc un membre de la classe peut être approprié (mais le profil d'abord, ne faites pas simplement une optimisation prématurée).
Polygnome
merci beaucoup les gars, en particulier Luaan car je me posais des questions sur ce problème de "mise en cache" pendant que j'écrivais la question d'origine (mais je ne savais pas vraiment comment formuler cela). Je vais certainement adopter autant que possible l'approche «locale». merci pour toute la grande aide des gars habituels.
Big T Larrity
2

La réponse de Josh Petrie est très bonne - voici une perspective complémentaire.

Lorsque vous travaillez avec du code dont vous comprenez assez bien le domaine, vous pouvez étendre les variables là où elles ont du sens.

Par exemple, si j'ai une Personclasse avec une waveGoodbyeméthode, il est possible que ma classe n'ait pas d' handobjet auparavant et que je puisse le déclarer localement dans waveGoodbye. Maintenant, il est évident qu'une personne a une main, vous pouvez donc naturellement la déclarer membre Personsans y penser, mais le même problème s'applique.

Si vous déclarez handlocalement, vous pouvez ajouter plus tard une karateChopméthode qui nécessite également un coup de main. C'est à ce moment que la déclaration de variables localement peut devenir problématique - car les développeurs débutants se rabattent souvent sur la copie / collage de la déclaration waveGoodbyeet vous avez maintenant le même concept situé à deux endroits. Tout changement doit handensuite être modifié aux deux endroits et commence ainsi une colline de bogues de fourmis .

Donc dans l'ensemble,

  1. Si vous êtes confiant dans le placement de votre déclaration, adaptez-la à l'endroit où cela a du sens.

  2. Si vous n'êtes pas sûr, démarrez local et assurez-vous de refactoriser lorsque vous obtenez une bouffée de réutilisation de code.

Edit: Oh et ne faites pas la même erreur que j'ai de passer trop de temps à déterminer où étendre vos déclarations. Il est difficile de comprendre la structure de vos données à l'avance, et lorsque vous écrivez votre code, la structure a un moyen de se révéler.

aaaaaa
la source
2
Le fait d'avoir des choses naturellement ordonnées, comme tout le monde Persondevrait avoir le membre hand si cela est pertinent dans l'application, aide souvent d'autres développeurs (la plupart du temps vous 6 mois plus tard) à mieux comprendre le code. Dans ce cas, il semble logique d'en avoir un en Rigidbodytant que membre de votre Playeret, je dis plus, même si cela implique de moins bonnes performances. Dans les jeux vidéo, c'est un point pertinent à considérer, mais je pense que dans le code , être clair est souvent plus important
également
1
excellentes réponses merci les gars. Je n'essaie pas de ressembler à un tout savoir, mais toutes ces réponses viennent de réaffirmer ce que je pensais déjà, donc pour une fois je suis très heureux et je fais de beaux progrès dans mes jeux. En ce moment, je fais un jeu de football en 3D avec des animations appropriées et tout, faisant de véritables progrès: D bientôt, je serai ici pour avoir de l'aide sur la façon de le faire à 2 joueurs et j'ose dire multijoueur en ligne: D amusez-vous les gars et merci encore!
Big T Larrity