Noticias

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

Hacer que el enemigo se destruya

Iniciado por brok, Noviembre 12, 2015, 07:43:10 PM

Tema anterior - Siguiente tema
Noviembre 12, 2015, 07:43:10 PM Ultima modificación: Noviembre 12, 2015, 07:48:20 PM por brok
El siguiente problema es que cuando instancio o duplicar el enemigo, al aver varios enemigos unos 5 o 6 no se detruye el enemigo que estoy golpeando, se destruye uno al hazar ¿como puedo solucionarlo?. using UnityEngine;
using System.Collections; public class vidaPlayerAI : MonoBehaviour
{
    Transform playerai;
    public static float vidaEnemigo = 100f;
    public static int ScoreValor = 10;    public static void RestarVidaEnemigo()
    {
        
        vidaEnemigo -= 20f;        if (vidaEnemigo <= 0f)
        {            Destroy(GameObject.FindGameObjectWithTag("Enemigo"));
            ScoreManager.score += ScoreValor;
            vidaEnemigo += 100;
                    }
        
    }
}Otro script.using UnityEngine;
using System.Collections;
public class ColisionPlayerAI : MonoBehaviour
{
    Transform player;
    AudioSource patadaAudio;
    public float sinkSpeed = 0.5f;
    void Start()
    {
        patadaAudio = GetComponentInParent<AudioSource>();
        player = GameObject.FindGameObjectWithTag("Player").transform;
    }
    void OnTriggerEnter(Collider colision)
    {        if (colision.gameObject.CompareTag("Player"))        {            vidaPlayer.RestarVida();
            patadaAudio.Play();
            Player.damaged = true;
            player.Translate(-Vector3.forward * sinkSpeed);
        }
    }
    
    
}Otro script. using UnityEngine;
using System.Collections;public class enemigoManager : MonoBehaviour {
    public GameObject enemigo;
    public float spawnTime = 10f;
    public Transform[] spawnPoints;
    // Use this for initialization
    void Start ()
    {
        InvokeRepeating("Spawn", spawnTime, spawnTime);
        
    }   
    void Spawn()
    {
                int spawnPointIndex = Random.Range(0, spawnPoints.Length);        Instantiate(enemigo, spawnPoints[spawnPointIndex].position, spawnPoints[spawnPointIndex].rotation);
    }

Vaya cacao te llevas.Cada enemigo debe de contener su propia clase de vida, no se si es una de esas dos que pones, porque lo mas conveniente es cuando un enemigo entra en colision con una bala, el mismo se quita vida y cuando llegue a cero se muere.Y tú ahí tienes en la otra clase un metodo que se llama RestarVida(es conveniente que los nombres de los métodos sean mas claros...)y no queda claro a quien se aplica.Espero que me hayas entendido pero solo leerte ya ha sido complejo de por si.

El metodo RestarVida se le aplica al jugador
Este script le resta la vida al enemigo,using UnityEngine;
using System.Collections;public class  ColisionPlayer: MonoBehaviour
{
    Transform playerT;
    public float sinkSpeed = 0.5f;
    AudioSource PatadaSonido;
    Player player;
    void Start()
    {
        playerT = GameObject.FindGameObjectWithTag("Player").transform;
        PatadaSonido = GetComponentInParent<AudioSource>();
        player = GetComponentInParent<Player>();
    }    void OnTriggerEnter(Collider colision)
    {        if (colision.gameObject.CompareTag("Enemigo"))        {            vidaPlayerAI.RestarVidaEnemigo();
            player.sliderAI.gameObject.SetActive(true);
            Player.damaged = true;
            PatadaSonido.Play();
            playerT.Translate(-Vector3.forward * sinkSpeed);
        }
        else
        {
            StartCoroutine(sliderEnemigo());
        }
        
   }    IEnumerator sliderEnemigo()
    {
        yield return new WaitForSeconds(5f);
        player.sliderAI.gameObject.SetActive(false);
        yield return null;
    }
}

Yo te recomiendo que cada enemigo tenga una clase base en la cual al entrar en un trigger con un objeto tipo bala o lo que le haga daño, entonces le reste vida. 

Destroy(GameObject.FindGameObjectWithTag("Enemigo"));puede ser que se te vuelva loco por destruir el objeto por el tag?si tienes varios objetos con ese mismo tag en escena no se veran influenciados?

Si ese creo yo que es el problema pero ya lo he intentado con un GameObject y el metodo RestarVidaEnemigo() esta en static y me sale error al poner la variable de GameObject, y el metodo RestarVidaEnemigo() tiene que estar en static, porque el script de colision esta dentro del esqueleto del personaje. 

Algo tan simple como un control de Salud no tiene que tener absolutamente nada estático, el problema se genera por 2 cosas, primero que cada vez que llamas la función RestarVidaEnemigo() esta se ejecuta en todos los Enemigos, y segundo "Destroy(GameObject.FindGameObjectWithTag("Enemigo"));" esto hace referencia al primer objeto que encuentra Unity con el tag "Enemigo". ¿Como se hace entonces?1- Creamos un componente y lo llamamos HealtControl (Nombre Opcional).2- Utilizamos 3 Métodos ApplyDamage ApplyCure, 1 Evento, 3 Variables.3- Actualizar cada parte del codigo donde aplicas cambia a la salud de cada personaje.Te Dejo el Codigo de Ej...
public class HealtControl : MonoBehaviour
{
public int MaxHealt = 100;
public int MinHealt = 0;

internal int CurrentHealt;
public delegate void DeathEvent();
public event DeathEvent Death:

void Start()
{
   if(CurrentHealt == 0)CurrentHealt = MaxHealt; // Asignamos MaxHealt como salud Inicial (CurrentHealt).
        Death += () => { Destroy(this.gameObject); } ;
 // Detectamos el Evento y Destruimos el Objeto.
}

internal void ApplyDamage(int Value)
{
   CurrentHealt -= Value; //Restamos Current healt por el valor de Value.
   CurrentHealt = Mathf.Clamp(CurrentHealt,MinHealt,MaxHealt); //Clampeamos los valores.
   if(CurrentHealt =< MinHealt)if(Death != null)Death(); //Detectamos si llego al minimo.
}

internal void ApplyCure(int Value)
{
   CurrentHealt += Value; //Aumentamos el valor de CurrentHealt.
   CurrentHealt = Mathf.Clamp(CurrentHealt,MinHealt,MaxHealt); //Clampeamos valores.
}
}

public class  ColisionPlayer: MonoBehaviour
{
    Transform playerT;
    public float sinkSpeed = 0.5f;
    AudioSource PatadaSonido;
    Player player;


    void Start()
    {
        playerT = GameObject.FindGameObjectWithTag("Player").transform;
        PatadaSonido = GetComponentInParent<AudioSource>();
        player = GetComponentInParent<Player>();
    }

    void OnTriggerEnter(Collider colision)
    {

        if (colision.gameObject.CompareTag("Enemigo"))
        {      
            //Vamos a utilizar una referencia a HealtControl para acceder a su metodo ApplyDamage().
            //Luego que hacemos la comprobacion de que existe dicho componente, vamos a llamar a la funcion ApplyDamage();
            var healt = colision.gameObject.GetComponent<HealtControl>(); //Tomamos el Componente HealtControl de la referencia.
            if(healt != null)healt.ApplyDamage(10);//Comprobamos si no es nulo y llamamos la funcion deseada.


            player.sliderAI.gameObject.SetActive(true);
            Player.damaged = true;
            PatadaSonido.Play();
            playerT.Translate(-Vector3.forward * sinkSpeed);


        }
        else
        {
            StartCoroutine(sliderEnemigo());
        }
       
   }

    IEnumerator sliderEnemigo()
    {
        yield return new WaitForSeconds(5f);
        player.sliderAI.gameObject.SetActive(false);
        yield return null;
    }

}
No te olvides de pasar por mi canal de YT, vas a entender cómo funcionan las variables con diferentes tipos de protección y acceso.
Otra Cosa, si necesitas detectar colisiones de cada parte del cuerpo ejemplo, Mano, Pie, Cabeza, es mejor crear referencia a las mismas y utilizar Physics comprobar la colisión. Código Ej.
public class BoneCollision : MonoBehaviour
{
//Creamos variables de referencia
public Transform[] BoneRef;
//Creamos Eventos
public delegate void Col(Transform ColRef);
public event Col ColBone;
//Conf
public float RadiusDetect = 5;
public LayerMask LayerCol;


void Update()
{
   //Creamos todos los los SphereCast para la deteccion de colision.
   RaycastHit hit;            
   foreach(Transform bone in BoneRef)
   {
      if (Physics.SphereCast(bone.position, RadiusDetect, bone.forward, out hit, 1,LayerCol))
        {
           if(ColBone != null)ColBone(hit.transform);
        }
   }        
}

void Start()
{
   ColBone += ((Transform Ref)=>
   {
      print(Ref.name);
      //Podemos Aplicar daño tambien
      var healt = Ref.GetComponent<HealtControl>(); //Tomamos el Componente HealtControl de la referencia.
            if(healt != null)healt.ApplyDamage(10);//Comprobamos si no es nulo y llamamos la funcion deseada.
   });
}
}
Todo esto lo hice sin comprobar si funcionaba, solo lo escribi..Este componente lo Asignas al Player y detecta todas las colisiones del player. Luego a la IA.. BoneRef -> Asignalo desde el inspector con el transform de la mano, pies y todos los que quieras que detecten colisión.Radius -> Radio del Collider de detecciónLayerCol -> Capas con la que queremos que colisione Saludos. 

Muchas gracias francoe1 aver si lo arreglo asin.

Noviembre 13, 2015, 05:40:54 PM #8 Ultima modificación: Noviembre 13, 2015, 06:06:20 PM por brok
Se lo he intentado implementar pero sin exito siento mucho por todo lo que me as ayudado francoe1 pero no me resta vida ni destruye a ninguno ni al player ni al enemigo, de todas formas muchas gracias.Me sale un error en esta linea en el =<.el <.Severity    Code    Description    Project    File    Line
Error    CS1525    Invalid expression term '<'    curso.CSharp    C:\Users\ono\Documents\curso\Assets\script2\HealtControl.cs    24 
if(CurrentHealt =< MinHealt)if(Death != null)Death(); //Detectamos si llego al minimo.

Noviembre 13, 2015, 07:03:19 PM #9 Ultima modificación: Noviembre 13, 2015, 07:08:14 PM por brok
Ya lo consegui pero le he puesto que le reste la vida al enemigo 20 y tengo que pegarle 7 o 9 patadas para restrle la vida y que destruya ell enemigo o me choco con el y lo destruyo.

El error es justamente por que esta mal puesta la expresión.. un error mio.
if(CurrentHealt <= MinHealt)if(Death != null)Death(); //Detectamos si llego al mínimo.
Solo cambia el "=<" por "<=" y llisto.
El problema de chocar y destruir es que deberias generar eventos, por ejemplo que al lanzar un Puñetazo se active la detección de la Mano si no estas atacando no deberia esta comprobando colisiones.

Noviembre 13, 2015, 09:07:40 PM #11 Ultima modificación: Noviembre 13, 2015, 09:09:39 PM por brok
Gracias, ya lo arregle supuse que era eso y lo correji, nuevamente gracias por la informacion ¿dime cual es tu canal de youtube? que no lo encuentro.


Noviembre 14, 2015, 07:53:26 PM #13 Ultima modificación: Noviembre 14, 2015, 08:07:52 PM por brok
Modifique el codigo y ahora no me resta vida ni destruye ni me da ningun error ¿que puedo estar haciendo mal? using UnityEngine;
using System.Collections;
using System;public class vidaPlayerAI : MonoBehaviour
{
    public delegate void DeathEvent();
    public event DeathEvent Death;
    public int vidaEnemigoMax = 100;
    public int vidaEnemigoMin = 0;
    public int vidaEnemigoAI;    public int ScoreValor = 10;    public void RestarVidaEnemigo(int Value)
    {
        vidaEnemigoAI -= Value;
        vidaEnemigoAI = Mathf.Clamp(vidaEnemigoAI, vidaEnemigoMin, vidaEnemigoMax);
        if (vidaEnemigoAI <= 0) if (Death != null) Death();
    }        void Update()
    {
        if (vidaEnemigoAI == 0)
        
            vidaEnemigoAI = 100;
            Death += () => { Destroy(this.gameObject); };
            
                    if (vidaEnemigoAI == 0)
        {
            ScoreManager.score += ScoreValor;
            aumentarVidaEnemigo(0);
        }
            
        
        
                 }
    void aumentarVidaEnemigo(int Value)
    {
        vidaEnemigoAI += Value;
        vidaEnemigoAI = Mathf.Clamp(vidaEnemigoAI, vidaEnemigoMin, vidaEnemigoMax);
    }
} Otro script using UnityEngine;
using System.Collections;public class  ColisionPlayer: MonoBehaviour
{
    Transform playerT;
    public float sinkSpeed = 0.5f;
    AudioSource PatadaSonido;
    Player player;
    CapsuleCollider col;
    void Start()
    {
        playerT = GameObject.FindGameObjectWithTag("Player").transform;
        PatadaSonido = GetComponentInParent<AudioSource>();
        player = GetComponentInParent<Player>();
            }    void Update()
    {
        var healt = col.gameObject.GetComponent<vidaPlayerAI>();
        if (healt != null) healt.RestarVidaEnemigo(20);
    }    void OnTriggerEnter(Collider colision)
    {        if (colision.gameObject.CompareTag("Enemigo"))        {
            var healt = colision.gameObject.GetComponent<vidaPlayerAI>();
            if (healt != null)
            
                healt.RestarVidaEnemigo(20);                player.sliderAI.gameObject.SetActive(true);
                Player.damaged = true;
                PatadaSonido.Play();
                playerT.Translate(-Vector3.forward * sinkSpeed);
                        
        }
        else
        {
            StartCoroutine(sliderEnemigo());
        }
        
   }    IEnumerator sliderEnemigo()
    {
        yield return new WaitForSeconds(5f);
        player.sliderAI.gameObject.SetActive(false);
        yield return null;
    }
}Me da errorvar healt = col.gameObject.GetComponent<vidaPlayerAI>();NullReferenceException: Object reference not set to an instance of an object
ColisionPlayer.Update () (at Assets/script/player/ColisionPlayer.cs:24) 

Noviembre 15, 2015, 10:47:00 AM #14 Ultima modificación: Noviembre 15, 2015, 10:50:59 AM por brok
Ya esta arregkado solo me falta mejorar el script de vida para que recarge mas rapido.using UnityEngine;
using System.Collections;
using System;public class vidaPlayerAI : MonoBehaviour
{
    public delegate void DeathEvent();
    public event DeathEvent Death;
    public int vidaEnemigoMax = 100;
    public int vidaEnemigoMin = 0;
    public static int vidaEnemigoAI;
    int valorScore = 10;   void Start()
    {
        if (vidaEnemigoAI <= 0)
        vidaEnemigoAI = vidaEnemigoMax;
        Death += () => { Destroy(gameObject); };
        ScoreManager.score += valorScore;
        aumentarVidaEnemigo(0);
    }
           public void RestarVidaEnemigo(int Value, Vector3 hitPoint)
    {
        vidaEnemigoAI -= Value;
        vidaEnemigoAI = Mathf.Clamp(vidaEnemigoAI, vidaEnemigoMin, vidaEnemigoMax);
        if (vidaEnemigoAI <= 0) if (Death != null) Death();
    }
    public void aumentarVidaEnemigo(int Value)
    {
        vidaEnemigoAI += Value;
        vidaEnemigoAI = Mathf.Clamp(vidaEnemigoAI, vidaEnemigoMin, vidaEnemigoMax);
    }    

Etiquetas: