Noticias

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

Dudas sobre qué métodos usar

Iniciado por Biarox1166, Julio 28, 2016, 04:10:05 AM

Tema anterior - Siguiente tema
Julio 28, 2016, 04:10:05 AM Ultima modificación: Septiembre 16, 2016, 02:22:34 PM por pioj
Hola, quería ver si alguien me puede decir qué es mejor a la hora de hacer una script de detección(en este caso, para detectar al jugador) y de paso sacarme algunas dudas con respecto a las animaciones y movimiento. Las forma que uso es mediante un trigger(sphere collider), la cosa es que quizás hay un método mejor o más practico. Les dejo la script que hice:
 

using UnityEngine;
using System.Collections;
public class ControladorEnemigo : MonoBehaviour {
public enum Estado{
   Idle,
   Corre,
   Ataca1,
   Ataca2,
   Baila,
}
public Estado EstadoActual;
public Animator ani;
public Rigidbody rb;
public Transform Player;
public float velocidad;
public float Damage;
public float MaxCercania;
public bool Detectado;
 
// Use this for initialization
void Start () {

   Detectado = false;
   ani = GetComponent<Animator>();
   rb = GetComponent<Rigidbody>();
   EstadoActual = Estado.Idle;
}

// Update is called once per frame
void Update () {
   float Distancia = Vector3.Distance(transform.position, Player.position);
   if(EstadoActual == Estado.Ataca1){
      ani.Play("AtaqueBase");
   }
   if(EstadoActual == Estado.Ataca2){
      ani.Play("AtaqueMax");
   }
   if(Detectado){
         transform.LookAt(Player);
      if(Distancia < MaxCercania){             
         StartCoroutine(TiempoAtack());
         }
         else{
         if(Distancia > MaxCercania){                              
            rb.AddForce(transform.forward * velocidad);                
            ani.Play("Correr");
            EstadoActual = Estado.Corre;
         }
      }
   }
   RaycastHit hit;
   if(Physics.Raycast(transform.position, transform.forward, out hit, 2)){
      if (hit.collider.tag == "Jack"){
         SaludyMana.Salud -= Damage * Time.deltaTime;
      }
   }
}
IEnumerator TiempoAtack () {
   EstadoActual = Estado.Ataca1;
   yield return new WaitForSeconds(3);
   EstadoActual = Estado.Ataca2;
   //yield return new WaitForSeconds(3);
}
void OnTriggerEnter(Collider other){
   if(other.tag == "Jack"){
      Detectado = true;
   }
}
/*void OnTriggerExit(Collider other){
   if(other.tag == "Jack"){
      Detectado = false;
   }
}*/
 
}

 
AVISO: lo de los estado los puse nada más que para ver como eran XD(lo ví en un video pero no es algo que use a futuro).
 
Como ven es algo bastante simple pero bueno, ahora les digo mis otras dudas:
 

  1.    Con respecto al daño, esta bien el uso de ray´s? Ya que no se si(al tener muchos enemigos en escena) me baje el rendimiento, porque leí que los ray´s estan constantemente haciendo cálculos(disculpen si dije cualquier cosa XD).¿Alguna idea para mejorar eso?


  2.    ¿Hay alguna forma de utilizar los "WaitforSecond" sin el uso de corutinas?Ya que en la scripting reference de Unity(mi biblia durante todo esto jaja) muestra su uso con corutinas y como no conozco muy bien sobre ellas(osea ví videos y demás pero sigo sin entender su uso ) quizas me complique más adelante.


  3.    ¿Ahora con respecto a el movimiento está bien el uso de AddForce?


  4.    Y mi última duda y no jodo más, como pueden ver con las animaciones(Uso un controller que hice) pero no utilicé transiciones ya que no me gusta usar lo de los parámetros y eso, por eso, reproduzco los "States" con la variable "Play" del animator. La cosa es que Dispongo de dos ataques: el base(uno simple el cual repito un par de veces) y el Max(que quiero que lo haga por ejemplo, después de X "ataques base"). Lo que no sé como hacer, es obtener la información de cuántas veces se reprodujo la animación base(creo que se hace con una variable llamada "StateInfo" o algo así pero no se bien cómo implementarla) y cómo "pararla"(si es que se está reproduciendo) para que de paso a la animación Max.


Ufff ajajaj, disculpen si escribí mucho pero quiero aprender bien esto que siempre me detiene a la hora de programar. De antemano gracias 
 
haaa y una cosa más jaajaj hay otra forma de que el enemigo "mire" al player que no sea LookAt? ya que cuando se acerca mucho(o salto muy cerca de él) todo el "cuerpo" se direcciona hacia el player y se pierde el realismo. Por eso si existe otra forma o alguna solución a este problema agradecería que me lo contaran. Ahora así chau XDD

Hola @Biarox1166
 
1. Como bien dices, es cierto que los raycast estan haciendo calculos constantemente ... siempre que se cumplan dos condiciones : Que el raycast este dentro del Update y que no este dentro de ningun condicional. Pero la ventaja del raycast en relacion a otros metodos como los colliders es que los primeros solo calculan un punto mientras los colliders comprueban muchos mas puntos de collision, numero que aumenta en funcion del collider escogido (una esfera tendra mas calculos que un cuadrado) ... por lo tanto el uso de raycast ya es correcto.
 
2. Que yo sepa no, el uso de WaitForSeconds solo es para corrutinas ... pero si quieres utilizar eso mismo en otro tipo de funcion, por ejemplo yo te lo recomendaria en donde tienes puesto el ataque para que no baje la vida constantemente, puedes hacerte un simple temporizador o cooldown.
 
3. Si se trata del movimiento de personajes, yo te recomendaria otras funciones que son mucho mas especificas y que ofrecen un mejor resultado para esa finalidad por ejemplo Move del componente CharacterController. AddForce lo veo mas apropiado para objetos que les añades una fuerza por ejemplo proyectiles o cualquier tipo de vehiculo ...
 
4. No controlo el tema de animaciones.
 
Para que el enemigo mire al personaje pero que no se incline cuando saltes, puedes utilizar perfectamente el LookAt pero teniendo la precaucion de cambiar la coordenada Y del vector que le pasas al LookAt para que sea la misma que el enemigo, no es nada complicado:
 

Vector3 direccion = personaje.position - enemigo.position;
direccion.Set (direccion.x, enemigo.position.y, direccion.z);
enemigo.LookAt (direccion);

 
 

Con el AnimatorController de Unity no se suele utilizar enumeración de Estados, para realizar transiciones entre animaciones.
 
El propio AnimatorController te permite establecer parámetros(variable, exit) para cambiar de la animación AtaqueBase-->AtaqueMax sin utilizar código.
 
Luego, dentro del clip de animación puedes crear eventos para llamar alguna función para realizar alguna acción/sonido/efectos sin utilizar corrutinas de tiempo.
 
 
 
________
 
 
 
Sobre el rendimiento de los Raycast, puedes utilizar un SphereCollider tipo Trigger emparentado al player, para que cuando el resto de actores entre/salgan de la esfera modifiquen su layer(etiqueta) que será utilizada en el Raycast para limitar el rango de colliders utilizado en la búsqueda.

Cita de: kaito date=1469699725Sobre el rendimiento de los Raycast, puedes utilizar un SphereCollider tipo Trigger emparentado al player, para que cuando el resto de actores entre/salgan de la esfera modifiquen su layer(etiqueta) que será utilizada en el Raycast para limitar el rango de colliders utilizado en la búsqueda.
   


buena idea! me la apunto

Cita de: kaito date=1469699725Sobre el rendimiento de los Raycast, puedes utilizar un SphereCollider tipo Trigger emparentado al player, para que cuando el resto de actores entre/salgan de la esfera modifiquen su layer(etiqueta) que será utilizada en el Raycast para limitar el rango de colliders utilizado en la búsqueda.
   


Es posible hacer esto que mencionas, y es posible que facilitara el trabajo al raycast ... pero teniendo en cuenta que los SphereCollider de por si ya consume mucho mas recursos (es el collider que mas calculo utiliza) que el raycast, la suma de las dos cosas no compensan.
 
Por poner un ejemplo que se vea facil, con una situacion fuera de la programacion, imaginate que te quieres comprar un coche de 30.000€ ... pero no quieres gastarte tanto dinero. Alguien te aconseja que compres el coche sin motor para que asi te salga un poquito mas barato, y en lugar de 30.000€ ahora te costara 25.000€ ... luego solo tendras que comprar un motor por 200.000€ por lo que el coche te ha salido mas barato pero la suma seran 225.000€ en lugar de los 30.000€ iniciales.
 
En el ejemplo del coche, ya se que un motor no cuesta tanto dinero xDDD lo importante del ejemplo es ver que aunque puedas ahorrar un poquito de consumo en una tarea, si el medio para conseguirlo va a llevar ligado un consumo mucho mayor que anteriormente ... no te saldra nunca a cuenta. Y un SphereCollider consume muchos mas recursos que un raycast.

Para el punto 1, una cosa que me parece muy elegante es crear una matriz con la parte entera de las coordenadas de los objetos (Transform) que quieres chequear. En tu caso si son varios enemigos y un sólo jugador incluso más fácil, no necesitas la matriz, simplemente puedes que el jugador informe de la parte entera de sus coordenadas en alguna parte publica y accesible a los enemigos. En el update haces la comparación de si está a -1 de diferencia en X, Y y Z en un if. Al ser enteros la comparación es muy rápida, si no cumple, ya no sigue. Si cumple entonces entras en el if y ya ahí haces las comprobaciones "finas".

Muchas gracias @Arthure me ayudó bastante lo que me dijiste(principalmente lo del LookAt que no sabía, soy nuevo en esto de programar XD) ahora es hora de implementarlo.... : p 

Cita de: Arthure date=14696979892. Que yo sepa no, el uso de WaitForSeconds solo es para corrutinas ... pero si quieres utilizar eso mismo en otro tipo de funcion, por ejemplo yo te lo recomendaria en donde tienes puesto el ataque para que no baje la vida constantemente, puedes hacerte un simple temporizador o cooldown.
   


Una pregunta, ¿cómo sería el uso del temporizador? ¿sería algo como que me fije cuánto tiempo tarda en finalizar la animación y en base a eso quitar daño "acorde" a la animación?

Hola @Biarox1166
 
No existe un uso del temporizador ... porque no existe tal componente como tal, te lo tienes que "fabricar" tu mismo (mediante codigo) y por lo tanto el uso dependera de ti mismo, o de tu codigo mejor dicho : puedes hacerlo tipo cronometro, cuenta atras, etc. segun tus necesidades. Es muy facil y hay miles de ejemplos por todos lados sobre eso, busca informacion sobre Time.deltaTime.
 
Sobre las animaciones, como ya comente, no tengo ni idea puesto que eso pertenece mas a otro campo que no es el mio pero si lo que pretendes es utilizar el tema temporizador para controlar las animaciones ... me suena (no estoy seguro porque nunca lo he utilizado) que mediante el controlador de animaciones de Unity puedes consultar el estado de la animacion por lo que no seria necesario un temporizador externo.

Agosto 03, 2016, 12:15:09 AM #9 Ultima modificación: Agosto 03, 2016, 03:32:21 AM por Biarox1166
No, sabía lo de que no existe un "temporizador", lo que quise decir era como utilizarlo en base a las animaciones. Pero igual aprendí a usar los eventos en las animaciones, cosa que me solucionó la mayoría de las dudas que tenía con respecto a las animaciones. Pero igual muchas gracias @Arthure por responder todo y rápido gracias!!!

Etiquetas: