¿Cómo debo implementar la "conciencia" enemiga de las unidades?

12

Estoy usando Unity3d para desarrollar un prototipo de juego híbrido RTS / TD. ¿Cuál es el mejor enfoque para la "conciencia" entre las unidades y sus enemigos? ¿Es sensato que cada unidad verifique la distancia a cada enemigo y se enfrente si está dentro del alcance?

El enfoque al que me dirijo ahora es tener una esfera de activación en cada unidad. Si un enemigo entra en el gatillo, la unidad se da cuenta del enemigo y comienza a verificar la distancia. ¿Esto ahorra algunos cheques innecesarios?

¿Cuál es la mejor práctica aquí?

Phil
fuente
Debo agregar que el recuento de unidades / enemigos estará en la escala del Comandante Supremo
Phil

Respuestas:

10

Examine las jerarquías de volumen delimitador (BVH). Se utilizan con mayor frecuencia en la detección de colisiones para reducir la cantidad de comprobaciones necesarias al calcular colisiones o en la renderización para realizar sacrificios de objetos en objetos. Como ya está usando esferas, sugeriría un árbol de esferas, aunque otros volúmenes como AABB pueden ser más eficientes. No estoy seguro de qué tipo de soporte tiene Unity para cosas como nunca lo he usado, pero probablemente ya haya algo para esto dentro de la detección de colisiones o las partes del motor.

Básicamente, querrás agrupar a los enemigos que están cerca uno del otro en múltiples esferas principales. Cuando se mueve una unidad, verificaría su esfera de disparo contra la esfera principal en lugar de verificar a cada enemigo. Si la esfera de activación se cruza con la esfera principal, verificaría a cada enemigo dentro. Si no es así, puedes descartar a todos los enemigos que están dentro de él. Debería configurar varios niveles de esferas en función del tamaño máximo de la esfera o el recuento de enemigos para cada esfera y realizar la verificación desde una esfera de nivel superior. Entonces es solo cuestión de caminar por el árbol para controlar a cada enemigo sin necesidad de realizar la verificación de distancia para cada uno.

Pasos necesarios para cada cuadro:

  1. Mover enemigos
  2. Reconstruir / actualizar el BVH para nuevas posiciones enemigas
  3. Mueve las unidades y verifica contra el árbol de la esfera.

Esto puede reducir los controles necesarios cuando hay muchos enemigos, pero la sobrecarga de actualizar y almacenar el árbol puede no valer la pena cuando no hay tantos. No estoy familiarizado con el Comandante Supremo para saber lo que buscas, así que solo estoy asumiendo 'cientos'. Deberá realizar un perfil en diferentes situaciones para averiguar si la sobrecarga le valdrá la pena.

Joel Baker
fuente
3
+1 este enfoque será más simple, aunque tendrá algunos errores. OP puede querer implementar esto y luego implementar algo como un octree. Además, en la mayoría de los RTS, las unidades reaccionan con cierto retraso. De hecho, la mayoría de las IA en los juegos se calculan entre 10 y 30 cuadros por segundo, donde el juego puede ejecutarse a 30-60 cuadros por segundo (los números son, por supuesto, aproximaciones).
Samaursa
Gracias, esto era exactamente lo que necesitaba para llevarme un paso más allá. Buscaré BVH y cómo implementarlo en Unity. ¡Publicación muy pedagógica e informativa! +1
Phil
Ah, y echa un vistazo a Supreme Commander si estás en RTS. Es un juego muy agradable, como lo son todos los juegos de Chris Taylor.
Phil
7

No es necesario implementar BVH, ya que el motor de colisión de Unity ya lo hace por usted.

Simplemente conecte un gran gatillo delimitador-esfera a cada unidad (que representa su gama) y manejar la OnCollisionEnter()y OnCollisionExit()devoluciones de llamada para realizar un seguimiento de los cuales enemigos están dentro del rango de cada unidad.

Tenga en cuenta que el caso que le interesa es cuando otra unidad choca con la esfera, no cuando la esfera de otra unidad choca con la esfera.

BlueRaja - Danny Pflughoeft
fuente
1
Creo que esto necesita ser votado al menos justo por encima de la respuesta aceptada. La respuesta aceptada es buena para estudiar, pero esta respuesta debe estar en la parte superior ya que esta es la forma más práctica.
Varaquilex
Creo que quieres decir OnTriggerEnter()y OnTriggerExit(), ¿verdad?
Jibb Smart
1

Otra solución que se escala muy bien y puede usarse para una multitud de otras cosas es un mapa de influencia. Genere un conjunto de mosaicos de cuadrícula alrededor de la unidad para escanear dentro del radio X. Escanea estas fichas en busca de un enemigo que se encuentre en una de ellas. Si desea obtener los enemigos más cercanos, puede ordenar su conjunto por distancia.

Este podría ser el método más eficiente, especialmente si planea hacer otras cosas con el mapa de influencia como la niebla de guerra o la búsqueda de caminos.

Aquí hay un video que hice explicando el concepto: https://www.youtube.com/watch?v=MEd6XV2Pecw .

Y aquí hay una implementación: https://www.youtube.com/watch?v=y_ewoxlZlgc

Recomiendo no inicializar la colección de unidades del mosaico de cuadrícula al inicio, sino solo cuando se necesita la colección.

Alternativamente, puede usar una matriz de longitud X si sabe que nunca habrá más de X unidades en un mosaico.

JPtheK9
fuente