Który z tych dwóch kodów jest „lepszy”? Czy tworzysz zmienną lokalną czy zmienną klasową?

11

Robię więcej gier i zadaję głupie pytania.

Mam nadzieję, że ten jest bardzo krótki. Tworzę bardzo podstawową klasę, która po prostu przenosi obiekt Gracza, przykładając siłę do sztywnego ciała, ale zastanawiam się, czy powinienem odwoływać się do klasy rb, czy po prostu lokalnej zmiennej Aktualizuj każdą klatkę? (pamiętając, że już istnieje w klasie macierzystej jedności Monobehaviour.GameObject).

Zastanawiam się, czy wykonanie wielu zmiennych lokalnych spowolniłoby pętlę jako całość (przez local rozumiem wewnątrz samej funkcji, a nie na szczycie klasy - mam nadzieję, że użyję poprawnego terminu).

Oto, co mam na myśli, dwa sposoby, o których myślałem o zrobieniu tego:

public class Player : MonoBehaviour {

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

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

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

lub...

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
źródło
4
To bardziej przypomina pytanie do recenzji kodu SE.
Orphevs,
1
Możesz także uczynić właściwość float va class.
Czad
Prawdopodobnie w końcu rzeczywiście będę Czad, ponieważ użyję go w dwóch metodach w klasie. To był naprawdę prosty kod, aby uzyskać pytanie o zmienne lokalne vs klasy bez rozrzucania go dużą ilością kodu. Naprawdę lubię trzymać zmienne lokalne (i „na uboczu”, jak to gdzie!), Ale oczywiście muszę się upewnić, że nie zacznę duplikować rzeczy zamiast mieć jedną zmienną klasy dla każdej.
Big T Larrity,
Fragment kodu nie jest „kodem”. Pytanie o „który kod jest lepszy” sprawia, że ​​wyglądasz jak amator.
Miles Rout
1
Jestem amatorem, więc dobrze mi ze mną, dzięki Miles
Big T Larrity,

Odpowiedzi:

25

Ogólnie stwierdziłem, że zakres danych powinien być zawężony tak wąsko, jak to możliwe, aby zacząć i rozszerzać zakres w miarę potrzeb. Oznacza to, że jeśli można zrobić to zmienna lokalna zamiast członkiem, powinieneś zacząć tam.

Wynika to z faktu, że węższy zakres zmniejsza liczbę miejsc w kodzie, w których należy uzasadnić te dane, a tym samym zmniejsza liczbę miejsc, w których można o tym błędnie wnioskować (co prowadzi do błędów).

Właściwie zadeklarowanie samych zmiennych lokalnych nigdy nie będzie miało praktycznie wpływu na wydajność: są tanie, a nowoczesne kompilatory mogą nawet zoptymalizować „dodatki”.

Inicjowanie ich może stanowić problem; w twoim przypadku twoje sztywne ciało jest sprawdzane za każdym razem GetComponent, co ma pewne niezerowe koszty. Jeśli wiesz, że element sztywnego ciała nie zmieni się dla tego konkretnego obiektu gry, możesz go sprawdzić raz i zapisać wynik w zmiennej elementu i uniknąć niewielkiego narzutu na połączenie.

Jest mało prawdopodobne, że narzut w jednym przypadku będzie znaczący w tym jednym przypadku, ale z czasem robienie tego dla wielu składników może się sumować. Na pewno chcesz zastosować profiler.

Podsumowując: ogólnie rzecz biorąc, domyślnie jest to ustawienie tak lokalne, jak to możliwe, ale w tym przypadku prawdopodobnie rozsądne jest utworzenie rbczłonka, abyś mógł przeprowadzić wyszukiwanie od razu Awakei uniknąć konieczności wykonywania każdego FixedUpdatepołączenia.


źródło
1
dziękuję Josh, czułem, że lepiej byłoby zainicjować rb tylko raz i bardzo dziękuję za jasne wyjaśnienie, dlaczego. Miło jest wiedzieć na pewno, ponieważ nie byłem w 100% pewien, że GetComponent liczy się jako inicjalizacja za każdym razem lub po prostu „wyszukiwanie” z Monobehaviour. Ale teraz otrzymuję tyle podziękowań za superszybką pomocną odpowiedź
Big T Larrity
1
@SuperMegaBroBro GetComponent jest dość szybki - trudno byłoby dokonać jakiegokolwiek wyszukiwania o porównywalnej prędkości. Jeśli nie masz danych o wydajności, które sugerują, że jest to problem, trzymaj się podejścia „zachowaj lokalne”. Zawsze możesz go później zoptymalizować. Zobacz answer.unity.com/questions/185164/... Nie zapominaj, że buforowanie również nie jest bezpłatne - jeśli zbuforujesz każdy element GetComponentw grze, prawdopodobnie będzie to strata netto. Pomiar. Zidentyfikuj, gdzie warto zoptymalizować. Skoncentruj się na tworzeniu świetnej gry :)
Luaan,
1
Główną istotą, którą powinieneś usunąć z tej odpowiedzi (co jest całkiem dobre) jest: Jeśli chcesz wybrać kod, który jest najłatwiejszy do uzasadnienia, przetestować i upewnić się, że jest wolny od błędów, weź zmienną lokalną. Ale, jak zawsze, czasami musimy poświęcić się na doskonalenie kodu ze względu na wydajność, więc członek klasy może być odpowiedni (ale najpierw profil, nie rób po prostu przedwczesnej optymalizacji).
Polygnome,
dziękuję bardzo chłopaki, szczególnie Luaan, ponieważ zastanawiałem się nad tym problemem „buforowania”, kiedy pisałem oryginalne pytanie (ale tak naprawdę nie wiedziałem, jak to powiedzieć). Z pewnością będę w jak największym stopniu stosować podejście „lokalne”. dziękuję za wspaniałą pomoc jak zwykle chłopaki.
Big T Larrity,
2

Odpowiedź Josha Petrie jest bardzo dobra - oto uzupełniająca się perspektywa.

Kiedy pracujesz z kodem, który dość dobrze rozumiesz domenę, możesz zawęzić zmienne tam, gdzie mają sens.

Na przykład, jeśli mam Personklasę z waveGoodbyemetodą, możliwe, że moja klasa nie miała handwcześniej obiektu, więc mógłbym zadeklarować go lokalnie waveGoodbye. Teraz jest oczywiste, że dana osoba ma rękę, więc możesz oczywiście zadeklarować ją jako członka, Personnie zastanawiając się nad tym, ale ta sama kwestia ma zastosowanie.

Jeśli deklarujesz handlokalnie, później możesz dodać karateChopmetodę, która również wymaga ręki. To wtedy lokalne deklarowanie zmiennych może stać się problematyczne - ponieważ młodsi programiści często wracają do kopiowania / wklejania deklaracji, waveGoodbyea teraz masz tę samą koncepcję zlokalizowaną w dwóch miejscach. Wszelkie zmiany, które handnależy wprowadzić, muszą zostać zmodyfikowane w obu miejscach, aby w ten sposób rozpocząć wzgórze mrówek .

Więc w sumie

  1. Jeśli jesteś pewny co do umieszczenia swojej deklaracji, zawrzyj ją tam, gdzie ma to sens.

  2. Jeśli nie masz pewności, uruchom lokalnie i dokonaj refaktoryzacji, gdy pojawi się powiew ponownego użycia kodu.

Edycja: Och, nie popełniaj tego samego błędu, jaki mam, spędzając zbyt dużo czasu, zastanawiając się, gdzie zawrzeć zakres swoich deklaracji. Trudno jest zrozumieć strukturę danych z góry, a podczas pisania kodu struktura może się ujawnić.

aaaaaa
źródło
2
Także o rzeczy naturalnie uporządkowane, jak każdy Personpowinien mieć element hand , jeśli jego znaczenie we wniosku, często pomaga innych deweloperów (większość razy skorzystać z 6 miesięcy później), aby lepiej zrozumieć kod. W tym przypadku logiczne wydaje się mieć członka Rigidbodyjako członka Playeri, powiedzmy więcej, nawet jeśli oznacza to gorszą wydajność. W grach wideo jest to istotna kwestia do rozważenia, ale myślę, że w kodzie jasne jest często ważniejsze
podobnie
1
doskonałe odpowiedzi dzięki chłopaki. Nie staram się brzmieć jak wszystko, co wiem, ale wszystkie te odpowiedzi potwierdziły to, o czym już myślałem, więc tym razem jestem bardzo szczęśliwy i robię postępy w swoich grach. W tej chwili robię grę w piłkę nożną 3d z odpowiednimi animacjami i innymi krokami: D wkrótce będę tu potrzebować pomocy, jak zrobić to dla dwóch graczy i śmiem powiedzieć online mulitplayer: D miłych facetów i jeszcze raz dziękuję!
Big T Larrity,