Noticias

¡RECUERDA QUE SI ERES UN NUEVO USUARIO, DEBES PRESENTARTE PARA PODER PUBLICAR MENSAJES! | TENEMOS CANAL OFICIAL DE TELEGRAM: t.me/unity3dspain

Inteligencia Artificial

Iniciado por juanma_teso, Junio 24, 2015, 08:58:25 PM

Tema anterior - Siguiente tema
Hola a todos!! Con la llegada del verano y de las vacaciones    vuelvo a Unity para hacer otro jueguito, una vez hechos los controles básicos me he puesto con la inteligencia, la última que hice fue muy simple de unas pocas líneas, esta vez me gustaría algo un poco más complejo, al que se tome el tiempo de leerla (tampoco es muy larga) y me dé un par de ideas/consejos con la IA, con sus experiencias personales, se lo agradeceré muy y mucho.

IEnumerator Inteligencia () {
   if (esperar)
      yield return new WaitForSeconds (3);
   distancia = Vector3.Distance(objetivo.transform.position, transform.position);
   angulo = Vector3.Angle (transform.up, objetivo.transform.position - transform.position);
   direccion = - Vector3.Cross (transform.up, objetivo.transform.position - transform.position).normalized.z;
   //Debug.Log ("direccion: " + direccion);
   if (distancia < 15 - dificultad) {
      //Debug.Log("Cerca: distancia (" + distancia + ") < 10 * dificultad (" + (10 + dificultad) + ")");
      ruedas.Avanzar(this.rb, 0);
      if (angulo < 20 / dificultad) {
         //Debug.Log("En frente: angulo < 20 / dificultad - " + 20/dificultad);
         if(angulo < 10/ dificultad){
            if (canion.alcance - 5/dificultad > distancia){
               //Debug.Log("A tiro: alcance > distancia - " + distancia);
               yield return new WaitForSeconds(1/dificultad);
               if(Time.time > canion.tiempoDisparo)
                  canion.Disparo ();
               else {
                  if(canion.disparado && Time.time > canion.tiempoDisparado){
                     canion.Disparado();
                  }
               }
            } else{
               //Debug.Log("No llego: alcance < distancia");
               ruedas.Avanzar(this.rb, Mathf.Lerp(0,0.8f,1));
            }
         } else {
            ruedas.Girar(this.transform, 0.1f*direccion);
         }
      } else {
         //Debug.Log("Rotar: angulo > 20 /dificultad - " + angulo);
         ruedas.Girar(this.transform, 0.1f*direccion);
      }
   } else {
      //Debug.Log("Lejos: distancia (" + distancia + ") > 10 * dificultad (" + (15 -dificultad) + ")");
      if(angulo < 20 / dificultad){
         //Debug.Log("En frente: avanzar - " + angulo);
         ruedas.Avanzar(this.rb, Mathf.Lerp(0,1,1));
      } else if (angulo > 20 / dificultad && angulo < 90) {
         //Debug.Log("Rotar: angulo > 20/dificultad && angulo < 90 - " + angulo);
         ruedas.Avanzar(this.rb, 0.4f);
         ruedas.Girar(this.transform, 0.1f*direccion);
      } else {
         //Debug.Log("Rotar: angulo < 90 - " + angulo);
         ruedas.Avanzar(this.rb, 0.4f);
         ruedas.Girar(this.transform, direccion*0.1f);
      }
   }
   if (Time.time > tempo) {
      tempo += 2f / dificultad;
      esperar = true;
   } else
      esperar = false;
   yield return null;
}

Básicamente es buscar al player con pequeñas pausas cada cierto tiempo.

Mira yo soy fan de "si funciona, está bien" pero ese código es una monstruosidad. La idea de una IA es que sea escalable y legible.
 
Si quieres avanzar en IA tienes que separar la lógica, idealmente empieza aprendiendo sobre máquinas de estado finito.
 
Googlealo, entiende la teoría y luego busca ejemplos basados en Unity que puedas descargar y modificar.

Bien, en principio te daría una recomendación, Jamas utilices Corrutinas para algo tan importante en un juego.
 
La idea no esta mal, pero mezclas todo y eso si que es mala idea, en la programación hay que ser demasiado cuidadoso y prolijo, esto lleva a que la optimizacion y búsqueda de problemas sea 100% mas rápida y precisa. 
 
1- Divide tus acciones, por ejemplo los disparos deberías controlarlo con otra función.
 
2- Estas haciendo demasiados cálculos innecesarios. 
Para poder encontrar un objeto dentro de un Cono de visión puedes hacerlo con el sobrante de la división entre la Dirección Normalizada y Mi Vector de dirección Frontal, y si el Sobrante es Mayor que 0.7 entonces esta dentro de los 90º.

Direccion = Normalizar (Target - MiObjeto);
dot = Dot(Direccion , MiObjeto.Forward);
if (dot > 0.7)
{
   //Esta dentro del angulo de visión.
}

3- Debes Evitar el uso de tantas sentencias IF y aprender a utilizar delegados, switch y métodos con retornos de objetos diferentes a void. 
 
4- Por ultimo, creo que tienes bastante ingenio y te has currado algo que funciona, eso es un gran paso, pero para que las cosas queden mejor muchas veces hay que leer y planificar lo que necesitamos para que el código siempre tenga una dirección y no tener que estar retomando y modificando o hasta re programando secciones completas a causa de un mal planeamiento.
 
¡Información Importante!
Busca notas o documentos sobre FSM para Inteligencia Artificial en Juegos.
 
Te Dejo algunos..
1 - http://gameprogrammingpatterns.com/state.html" rel="external nofollow">http://gameprogrammingpatterns.com/state.html
2 - http://gamedevelopment.tutsplus.com/tutorials/finite-state-machines-theory-and-implementation--gamedev-11867" rel="external nofollow">http://gamedevelopment.tutsplus.com/tutorials/finite-state-machines-theory-and-implementation--gamedev-11867
3 - http://jessewarden.com/2012/07/finite-state-machines-in-game-development.html" rel="external nofollow">http://jessewarden.com/2012/07/finite-state-machines-in-game-development.html
 
Y Para finalizar, te dejo algo de Oro, esto tiene muchísima informacion sobre inteligencia artificial y dedicado a vídeo juegos.
http://www.gameai.com/sites.php%C2%A0" rel="external nofollow">http://www.gameai.com/sites.php 
 
Suerte y un Abrazo, cualquier duda, estamos para ayudar! 

Muchas gracias a los dos!! @francoe1@Kondor0
Funcionar, funciona, pero no estaba a gusto, necesitaba esas críticas, me pondré a leer, porque cuando empecé el script no tenía mucha idea de cómo simular el pensamiento de una persona!! jaja porque al final esa es la meta.

Buenas, para ser mas exactos la inteligencia artificial en los videojuegos no busca simular el pensamiento humano, eso es mucho mas complicado, mas bien busca imitar comportamientos suficientemente inteligentes para que parezca humanos. Yo te recomendaria, ademas de lo que te ha recomendado @francoe1, que mires: "Three States and a Plan: The A.I. of F.E.A.R." que es un paper sobre la inteligencia artificial que se utilizo en fear, explica los conceptos de arboles de decision.
 
Ademas si no quieres leer tanta documentacion en ingles te recomendaria dos potcast de Stratos en los que explican concepto como maquinas de estado finitas , blackboars o comportamientos basados en metas.
 
Te dejo el link a todas estas cosas :
 
http://alumni.media.mit.edu/~jorkin/gdc2006_orkin_jeff_fear.pdf" rel="external nofollow">http://alumni.media.mit.edu/~jorkin/gdc2006_orkin_jeff_fear.pdf
 
http://www.stratos-ad.com/forums/index.php?topic=16812.0" rel="external nofollow">http://www.stratos-ad.com/forums/index.php?topic=16812.0
http://www.stratos-ad.com/forums/index.php?topic=16850.0" rel="external nofollow">http://www.stratos-ad.com/forums/index.php?topic=16850.0
 
Saludos.

Cómo bien ha puesto @esr la IA en videojuegos se basa en evaluar y sugerir patrones de comportamientos en los NPC. Los behavior tree son el mejor ejemplo de uso para diseñar IA.  Si te fijas, funciona de la misma forma que las animaciones del Meccanim...

@pioj precisamente cuando busqué sobre las máquinas de estado me vino a la cabeza la estructura del Animator. Aunque ya he empezado un script nuevo, seguiré leyendo y escuchando todo lo que habéis pasado. @esr

Etiquetas: