En el motor Fuente (y su antecesor, goldsrc, terremoto), los objetos del juego se dividen en dos tipos, mundo y entidades. El mundo es la geometría del mapa y las entidades son jugadores, partículas, sonidos, partituras, etc. (para el motor de origen).
Cada entidad tiene una función de pensamiento , que hace toda la lógica para esa entidad.
Entonces, si todo lo que necesita ser procesado proviene de una clase base con la función de pensar, el motor del juego podría almacenar todo en una lista y, en cada cuadro, recorrerlo y llamar a esa función.
A primera vista, esta idea es razonable, pero puede requerir demasiados recursos si el juego tiene muchas entidades.
Entonces, ¿cómo se ocupa un motor como Source (procesar, actualizar, dibujar, etc.) de los objetos del juego?
<some commercial engine>
hace?Respuestas:
Bueno, prácticamente no hay otra forma de hacerlo: tendrá que recorrer y llamar
think()
a cada entidad al menos una vez cada pocos fotogramas.Podrías poner entidades en su propio hilo, pero entonces tienes toda la pesadilla de sincronización de estado, que definitivamente no vale la pena.
Es por eso que el motor Source pone un límite estricto al número de entidades que pueden existir al mismo tiempo : 4096 entidades, de las cuales solo la mitad (2048) pueden conectarse en red. Si superas cualquiera de estos límites, el juego se bloqueará.
Por eso también, al crear un mapa, recomiendan que no use más de aproximadamente 800 entidades.
fuente
Es probable que estos pasos que mencione se realicen en motores separados. Es solo que los motores de juego simples generalmente los tienen en una sola pasada. Su secuencia
se convierte
Physics Engine se encarga de las posiciones y los tamaños.
Game Logic Engine se encarga de interpretar qué cambió Physics Engine (podría obstruir algunos puntos de referencia ...), qué objetivos tienen los personajes y qué comportamiento deberían estar haciendo , ejecuta scripts programados (esta función de pensar ).
Drawing Engine dibuja qué objetos son visibles, y él sabe qué objetos son visibles porque los motores Quake hacen trampa aquí (ver la sección Dibujar).
Mi consejo para ti es más bien estudiar cómo se hacen las simulaciones en lugar de los motores de juego. Hay una gran cultura pop que relaciona el desarrollo de juegos y los motores de juegos están hechos en lenguajes imperativos (debido a la tradición y la velocidad); así que fue más esclarecedor para mí obtener buenos libros de texto (en lugar de teoría) y LUEGO mirar motores (práctica) en lugar de mirar motores y descifrar durante horas cómo lo hicieron.
Física
La noción completa de iterar todas las entidades y hacer {think, draw} probablemente conducirá a problemas. Habrá conflictos, etc. Creo que Valve tiene a Havok y creo que Havok se encarga de la física lo suficientemente correcta.
Pensar
La función de pensar se ejecuta cuando un tiempo en un juego es igual al tiempo en el siguiente pensamiento . Funciona de esta manera en el motor Quake, y el motor Quake es la base para los motores Half Life. NO se ejecuta cada vez.
Internamente, debería ser una simple iteración a través de una lista de entidades y verificar si ha pasado el tiempo para llamar a la función think. La complejidad temporal será O (N), donde N es el número de entidades.
Si hay una gran cantidad de entidades, debe medir cuánto mejorará los fps. Tenga en cuenta que, debido a la ley de Amdahl, es una aceleración potencialmente invisible. Quiero decir, simplemente iteras a través de todos los elementos y disminuyes y verificas un número.
Lo aceleraría clasificando las entidades por el siguiente pensamiento (crear una lista de punteros a entidades y ordenarlo cada vez; no una matriz de entidades, porque las entidades pueden cambiar su próximo pensamiento en cualquier momento, por lo que reorganizarlas en la matriz toma O (N) en lugar de O ( 1) en la lista).
También debe mirar el planificador O (1) en Linux .
Dibujar
El motor dibuja lo que es aproximadamente visible desde el área en la que se encuentra la cámara. El nivel del juego es la partición en un árbol, y un área es la hoja de ese árbol. No te molestaré con detalles al respecto ... Entonces, si una entidad es visible, se coloca en un conjunto de entidades visibles y se dibujan.
Almacenan qué áreas son áreas potencialmente visibles. Se llama "conjunto potencialmente visible", PVS para abreviar. Hay visualización de PVS , la cápsula verde es el jugador y a su alrededor se muestra lo que contiene su PVS.
fuente
En realidad, poner todo en una gran lista suele ser menos que deseable; Si tuviera que agrupar las entidades en listas basadas, por ejemplo, en su tipo, podría distribuir mejor el procesamiento en varios subprocesos. Por ejemplo, si sabe que todas las entidades de tipo Foo nunca interactúan con otras entidades durante la fase de simulación, puede descargarlas por completo. Si estuvieran esparcidos por todas partes en una gran lista singular, esto sería mucho más difícil de hacer.
Ni siquiera necesita necesariamente derivar todo de una clase base común en ese punto; Source se exagera con el abuso de herencia por lo que de otra manera podría implementarse como datos a ese respecto.
Por supuesto, siempre tendrá un límite superior en la cantidad de entidades que puede procesar por cuadro, incluso si comienza a descargar el trabajo a otros núcleos. No hay forma de evitar eso, solo necesita tener una idea de cuál es el límite en su implementación y tomar medidas para aliviarlo (eliminación adecuada de las fases de procesamiento en los objetos que no los necesitarán, evitando la granularidad excesiva en los objetos, etc. cetera).
fuente
Lo que debe tener en cuenta y esto, siguiendo el tren de pensamiento de las respuestas anteriores, es que su rendimiento también dependerá de cuándo y cómo llame a estas funciones de pensamiento.
Mirando el enlace que publicó en el motor de origen, también puede leer que puede configurar tiempos de reflexión y diferentes contextos de reflexión para cada una de sus entidades, además del límite difícil obvio que alguien ya señaló, esta será la clave para lograr un mayor rendimiento con un mayor número de entidades, ya sea mediante la creación de actualizaciones escalonadas que difunden el procesamiento hambriento de rendimiento a través de múltiples marcos de ejecución, o eliminando el procesamiento innecesario según el contexto actual (es decir, las entidades que están demasiado lejos o más allá de la percepción del jugador no necesitan el mismo nivel de "pensar en detalle" que los personajes que están cerca de un jugador simplemente no verán a un personaje a 2 millas de distancia mordiéndose la nariz).
Y hay otros niveles más específicos de optimización dependiendo de la lógica y la situación de tu juego específico.
fuente