Identyfikowanie zasobów w silniku gry?

12

Chcę zidentyfikować załadowane zasoby, ale nie wiem, który wybrać. Istnieją 2 opcje:

  • Nazwa (ciąg)

    • Jest to najłatwiejszy i najszybszy z unordered_map (O (1)), ale o wiele wolniej niż przy użyciu liczb całkowitych.
    • Łatwo zrozumiałe w kodzie.
  • Liczby całkowite

    • Najszybszy.
    • Nie są zrozumiałe w kodzie.

Wiem, że ciągi nie są tak bezpieczne ani szybkie, ale czy to takie złe, czy może liczy się tylko jako złe w tytule AAA? Mógłbym tworzyć wyliczenia, aby używać liczb całkowitych, ale jeśli załaduję scenę, zasoby itp. Z pliku w czasie wykonywania, nie będę mógł użyć wyliczeń. Czy istnieje sposób, aby te liczby całkowite były czytelne, jeśli są generowane w czasie wykonywania?

Wiem, że ten problem ma kilka wątków w całym Internecie, ale nie mogłem dowiedzieć się, jak ważne jest w jakich przypadkach.

Tudvari
źródło
10
Dlaczego nie wdrożenie obu? Wersja ciągu łączy się ze słownikiem <string, int>, który z kolei wywołuje słownik <int, Asset>. Możesz obejść warstwę opartą na łańcuchach w kodzie, ale użyj warstwy opartej na łańcuchach do interakcji użytkownika.
Krythic,
2
Poparłbym punkt @ Krythica. Jeśli twój kod lubi liczby całkowite ze względu na szybkość, pozwól mu używać liczb całkowitych. Jeśli Twoi użytkownicy lubią ciągi dla czytelności, pozwól im używać ciągów. Oba mogą współistnieć całkiem szczęśliwie (i możesz selektywnie kompilować wersję łańcuchową tylko do kompilacji programistycznych, jeśli chcesz całkowicie pominąć koszty ogólne w wersji)
DMGregory
Ten sam problem w nieco innym kontekście: Różne metody implementacji przedmiotu - jakie są różnice?
Filip.

Odpowiedzi:

19

Możesz wesprzeć oba.

Podczas gdy w środowisku wykonawczym często jest bardziej wydajne odwoływanie się do zasobów za pomocą liczby całkowitej lub podobnego klucza szybkiego porównywania, często jest bardziej wydajne w czasie projektowania, aby odwoływać się do nich z nazwy, ponieważ ludzie są znacznie lepsi w pracy z nazwami podobnymi enemy_bullet_casing_soundniż 72910613.

Użyj klucza liczb całkowitych, aby bezpośrednio wyszukać zasoby, i używaj tej liczby całkowitej w kodzie, gdzie to możliwe (gdzie możesz umieścić rzeczywistą wartość liczby całkowitej w zmiennej, a tym samym pracować z nią łatwiej). Zapewnij odwzorowanie od nazwy do tego klucza liczby całkowitej (zamiast bezpośrednio do zasobu) i używaj tego odwzorowania za każdym razem, gdy napotkasz odniesienia do zasobów, aby rozwiązać rzeczywisty klucz liczby całkowitej i znaleźć zasób.

Korzystanie z wyszukiwania opartego na nazwach znacznie ułatwi pracę z plikami danych, a mapowanie nazwy na szybszy klucz pozwoli zachować wszystkie ważne zalety szybszego klucza typu całkowitego w dowolnym miejscu.


źródło
Mój przypadek: chcę zmienić materiał obiektu, więc wysyłam żądanie z nazwą nowego materiału. (ciąg znaków) Następnie w systemie graficznym następuje wyszukiwanie na nieuporządkowanej mapie <ciąg znaków, wskaźnik>, a wskaźnik obiektu zostanie zastąpiony nowym wskaźnikiem. Więc w moim przypadku nie muszę konwertować go na liczbę całkowitą? (ponieważ konwertuję go na wskaźnik i przy częstych algorytmach używam wskaźników, używam tylko ciągów znaków do okazjonalnych rzeczy.)
Tudvari,
Czy powinienem używać liczb całkowitych zamiast wskaźników wszędzie tam, gdzie to możliwe? (Więc nie muszę dołączać pliku nagłówka np. Materiału.) Na przykład komponent renderera przechowuje teraz wskaźnik używanego materiału, który może być używany bezpośrednio przez silnik graficzny, ale muszę dołączyć Material.h . Ale kiedy przechowuję tylko liczby całkowite w komponencie renderera, nie muszę dołączać Material.h, ale muszę wykonać wyszukiwanie oparte na liczbach całkowitych w tablicy wskaźników. Myślę, że ten drugi jest lepszy. Czy to jest Czy powinienem to refaktoryzować?
Tudvari,
1

W moim projekcie używam ciągów mieszanych, które są przekształcane w czasie kompilacji w unikalne (życzę!) Liczby. Kiedy potrzebuję zasobu, na przykład tekstury, po prostu dzwonię

MngTexture->get(hash("my_texture"))

A ponieważ tworzę prostą strukturę systemu encji i muszę ładować dane komponentów z plików, stworzyłem prosty język, taki jak json, do przechowywania danych, ale można go kompilować (przekształcając słowa i znaki z cyfr na liczby oraz z ciągów znaków na wartości mieszane) . Na przykład, jeśli chcę połączyć teksturę z skrótem identyfikatora („moja_tekstura”) z „ball.PNG” w moim pliku danych, będę miał

|my_texture| = "ball.PNG"

Gdzie || to operator, który każe kompilatorowi mieszać słowo w środku.

Zasadniczo używam ciągów, które są odwzorowywane na int w czasie kompilacji (więc nie mają narzutu), zarówno w rzeczywistym kodzie, jak i w plikach, które są strumieniami do ładowania komponentów. Do obliczenia skrótu czas kompilacji wystarczy google go, jest to prosta funkcja 5-10 linii kodu.

Oczywiście możesz załadować ciąg z plików i mieszać go w czasie wykonywania, w tym przypadku nie musisz pisać słownika samodzielnie, ponieważ algorytm zrobi to za ciebie (tworzenie liczb całkowitych z ciągów), a ja think hasing jest co najmniej tak szybki jak wyszukiwanie na mapie, ze względu na lokalizację pamięci (po prostu zapętlasz ciąg znaków o długości kilku bajtów).

Mam nadzieję, że to może pomóc.

Liuka
źródło
0

Identyfikacja obiektu za pomocą łańcuchów nie jest optymalna, ints są znacznie bardziej wydajne. Dla wygody możesz utrzymywać tablicę ciągów (lub słownik) ciągów do ints, aby pomóc w czasie projektowania i podczas debugowania.

Radziłbym jednak, aby w swoim głównym kodzie gry odnosić się do obiektów tylko według ich liczb całkowitych (lub wyliczeń dla czytelności). Dzięki temu łatwiej jest rozbić tabelę ciągów jako oddzielny zasób. Jeśli Twój główny kod gry nie opiera się na tej tabeli ciągów, możesz go usunąć z wydanej gry, potencjalnie oszczędzając znaczną ilość pamięci - ważne, jeśli pracujesz nad grą mobilną i chcesz zachować rozmiary pobrań tak małe, jak możliwy.

steeveeet
źródło