¿Identificar activos en un motor de juego?

12

Quiero identificar mis activos cargados, pero no sé cuál debo elegir. Hay 2 opciones:

  • Nombre (cadena)

    • Esto es lo más fácil y también rápido con unordered_map (O (1)), pero mucho más lento que usar números enteros.
    • Fácilmente comprensible en el código.
  • Enteros

    • Lo más rápido.
    • No son entendibles en el código.

Sé que las cuerdas no son tan seguras o rápidas, pero ¿son tan malas o solo cuentan como malas en un título AAA? Podría hacer enumeraciones, para usar números enteros, pero si cargo la escena, los activos, etc. de un archivo en tiempo de ejecución, no puedo usar enumeraciones. ¿Hay alguna manera de hacer que estos enteros sean legibles si se generan en tiempo de ejecución?

Sé que este problema tiene algunos hilos en todo Internet, pero no pude averiguar qué tan importante es en qué casos es esto.

Tudvari
fuente
10
¿Por qué no una implementación de ambos? La versión de cadena se conecta a un Diccionario <cadena, int> que a su vez llama a Diccionario <int, Asset>. Puede eludir la capa basada en cadenas en el código, pero use la capa basada en cadenas para la interacción del usuario.
Krythic
2
En segundo lugar, el punto de @ Krythic. Si a su código le gustan los enteros para la velocidad, deje que su código use enteros. Si a sus usuarios les gustan las cadenas para la legibilidad, permita que sus usuarios usen cadenas. Los dos pueden coexistir bastante felices (y puede compilar selectivamente la versión de cadena solo en compilaciones de desarrollo, si desea omitir la sobrecarga por completo en el lanzamiento)
DMGregory
Mismo problema en un contexto ligeramente diferente: diferentes métodos de implementación de elementos: ¿cuáles son las diferencias?
Philipp

Respuestas:

19

Puedes apoyar a ambos.

Si bien a menudo es más eficiente en tiempo de ejecución a los activos de referencia por un entero o alguna clave similares compare-rápido-a, a menudo es más eficiente en tiempo de diseño para hacer referencia a ellos por su nombre, porque los seres humanos son mucho mejores para trabajar con nombres como enemy_bullet_casing_soundque 72910613.

Use una clave de entero para buscar los recursos directamente, y use este entero en el código siempre que sea posible (donde puede poner el valor real del entero en una variable y así trabajar con él más fácilmente). Proporcione una asignación de nombre a esa clave entera (en lugar de al recurso directamente), y use esa asignación cada vez que encuentre referencias con nombre a activos para resolver la clave entera real y encontrar el activo.

El uso de la búsqueda basada en nombres hará que sea mucho más fácil trabajar con sus archivos de datos, y asignar el nombre a una clave más rápida preservará todos los beneficios importantes de una clave de tipo entero más rápida en cualquier lugar donde sea necesario.


fuente
Mi caso: quiero cambiar el material de un Objeto, así que envío una solicitud con el nombre del nuevo material. (cadena) Luego, en el sistema de gráficos hay una búsqueda en un mapa no ordenado <cadena, puntero>, y el puntero del material del objeto será reemplazado por el nuevo puntero. Entonces, en mi caso, ¿no tengo que convertirlo en un entero? (porque lo convierto en puntero y en los algoritmos frecuentes uso punteros, solo uso cadenas para cosas ocasionales.)
Tudvari
¿O debería usar ID-s enteros en lugar de punteros donde sea posible? (Por lo tanto, no tengo que incluir el archivo de encabezado de, por ejemplo, el material). Por ejemplo, el componente de renderizador ahora almacena el puntero del material utilizado, que puede ser utilizado directamente por el motor de gráficos, pero tengo que incluir Material.h . Pero cuando almaceno solo enteros en el componente de renderizador, no tengo que incluir Material.h, pero tengo que hacer una búsqueda basada en enteros en la matriz de punteros. Creo que este último es mejor. ¿Lo es? ¿Debería refactorizar esto?
Tudvari
1

En mi proyecto utilizo cadenas hash, que se transforman, en tiempo de compilación en números únicos (¡lo deseo!). Entonces, cuando necesito un recurso, por ejemplo, una textura que simplemente llamo

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

Y dado que estoy creando un marco de sistema de entidad simple y necesito cargar datos de componentes desde archivos, creé un lenguaje simple como json para almacenar datos, pero es compilable (transformando palabras y caracteres de dígitos a números y de cadenas a valores hash) . Entonces, por ejemplo, si quiero vincular la textura con hash ID ("my_texture") a "ball.PNG" en mi archivo de datos tendré

|my_texture| = "ball.PNG"

Donde || es un operador que le dice al compilador que codifique la palabra dentro.

Entonces, básicamente, uso cadenas que se asignan a ints en tiempo de compilación (para que no tengan ninguna sobrecarga), tanto en el código real como en los archivos que son las secuencias para cargar componentes. Para calcular el hash un tiempo de compilación, simplemente búscalo en google, es una función simple de 5-10 líneas de código.

Por supuesto, puede cargar la cadena de sus archivos y hacer un hash en tiempo de ejecución, en este caso no tiene que escribir el diccionario por su cuenta porque el algoritmo lo hará por usted (creando enteros a partir de cadenas) y yo piensa que el hasing es al menos tan rápido como buscar en un mapa, debido a la localidad de la memoria (solo estás recorriendo una cadena que tiene unos pocos bytes de longitud).

Espero que esto pueda ayudar.

Liuka
fuente
0

Identificar objetos por cadenas no es óptimo, los ints son mucho más eficientes. Para mayor comodidad, puede mantener una tabla de cadenas (o diccionario) de cadenas a ints para ayudar en el momento del diseño y durante la depuración.

Sin embargo, recomendaría que dentro de su código de juego principal solo se refiera a los objetos por su ID entero (o una enumeración para facilitar la lectura). Hacer esto simplifica la división de la tabla de cadenas como un activo separado. Si el código principal de su juego no se basa en esta tabla de cadenas, puede eliminarlo del juego lanzado, lo que puede ahorrar una cantidad significativa de memoria, una consideración importante si está trabajando en un juego móvil y desea mantener los tamaños de descarga tan pequeños como posible.

steeveeet
fuente