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);
}
}
Odpowiedzi:
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
rb
członka, abyś mógł przeprowadzić wyszukiwanie od razuAwake
i uniknąć konieczności wykonywania każdegoFixedUpdate
połączenia.źródło
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 elementGetComponent
w grze, prawdopodobnie będzie to strata netto. Pomiar. Zidentyfikuj, gdzie warto zoptymalizować. Skoncentruj się na tworzeniu świetnej gry :)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
Person
klasę zwaveGoodbye
metodą, możliwe, że moja klasa nie miałahand
wcześniej obiektu, więc mógłbym zadeklarować go lokalniewaveGoodbye
. Teraz jest oczywiste, że dana osoba ma rękę, więc możesz oczywiście zadeklarować ją jako członka,Person
nie zastanawiając się nad tym, ale ta sama kwestia ma zastosowanie.Jeśli deklarujesz
hand
lokalnie, później możesz dodaćkarateChop
metodę, 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,waveGoodbye
a teraz masz tę samą koncepcję zlokalizowaną w dwóch miejscach. Wszelkie zmiany, którehand
należy wprowadzić, muszą zostać zmodyfikowane w obu miejscach, aby w ten sposób rozpocząć wzgórzemrówek.Więc w sumie
Jeśli jesteś pewny co do umieszczenia swojej deklaracji, zawrzyj ją tam, gdzie ma to sens.
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ć.
źródło
Person
powinien mieć elementhand
, 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łonkaRigidbody
jako członkaPlayer
i, 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