No tienes acceso a esta clase

¡Continúa aprendiendo! Únete y comienza a potenciar tu carrera

No se trata de lo que quieres comprar, sino de quién quieres ser. Invierte en tu educación con el precio especial

Antes: $249

Currency
$209

Paga en 4 cuotas sin intereses

Paga en 4 cuotas sin intereses
Suscríbete

Termina en:

12 Días
16 Hrs
23 Min
5 Seg

Comportamiento de enemigo

16/41
Recursos

Aportes 13

Preguntas 4

Ordenar por:

¿Quieres ver más aportes, preguntas y respuestas de la comunidad?

Segun lo visto hay un problema y es que a medida que el enemigo se acerca al jugador este empieza a disminuir su velocidad. Para solucionar esto, hay que dividir el vector direccion por su magnitud. asi:

transform.position += (Vector3)direction/direction.magnitude * Time.deltaTime * enemySpeed;

Reto 1

Reto 2

primero le damos al player un rigibody2d con gravity scale en 0
y tildamos is trigger
lo mismo con el enemigo
luego Generamos una valiable [serializeField] int PlayerHealt = 5;

private void OnTriggerEnter2D(Collider2D collision)
{
    if (collision.CompareTag("Enemy"))
    {
        PlayerHealt--;
        if(PlayerHealt<= 0)
        {
            gameObject.SetActive(false);
        }
    }
}

En el script del enemigo:
public void TakeDamage()
{
healt–;
if (healt <= 0)
{
Destroy(gameObject);
}

}

}
En el Script del Bullet
private void OnTriggerEnter2D(Collider2D collision)
{
if (collision.CompareTag(“Enemy”)) {
collision.GetComponent<Enemy1>().TakeDamage();
Destroy(gameObject);
}
}
}

Para mover un objeto a otro, se utiliza la resta de vectores.

Hola 😄
Con estos retos me sentí creativo y me puse a hacer las cosas de una forma un tanto diferente a lo venimos haciendo en el curso. No se como vaya a resultar a futuro conforme vaya creciendo el proyecto, pero es parte de la diversión 😜

<h3>Destruir el enemigo</h3>

Al principio solo agregue, dentro del script de Enemy, una condición de que se destruyera el gameObject cuando health fuese menor o igual a 0

Pero me sentí inspirado y decidí extraer el comportamiento de ser “dañable” a otro script, para poder reutilizarlo luego con el Player u otros objetos

Para este comportamiento “Damageable” se me ocurrió que iba a querer que pudieran suceder diferentes cosas al gameObject cuando se quedara sin vida, así que le agregué creé un event llamado OnEmptyHealt que me sirviera para ejecutar N cantidad de comportamientos cuando el gameObject en cuestión se quedase sin vida

Esto tiene que ver con Delegados y Eventos

Una explicación algo burda del código de arriba (que bien puede que no sea del todo correcta, pero me ayuda a entenderle un poco) sería

En la línea 6 digo:
He aquí un tipo de delegado, que recibe cero parámetros y no retorna ningún valor, este tipo de delegado se llama EmptyHealthAction

En la línea 7 digo:
He aquí un evento cuyo nombre es OnEmptyHealth, que puede ejecutar delegados del tipo EmptyHealthAction

y en las líneas 11 y 12 digo:
si la vida es menor o igual a cero y el evento OnEmptyHealt tiene algún delegado a ejecutar, invoca al evento OnEmptyHealth para que ejecute todas los delegados que tiene asignados

Ya con eso listo, en el OnTriggerEnter2D de Bullet cambié el componente se obtiene de Enemy a Damageable

Ahora lo que me faltaba era crear scripts/comportamientos independientes que pudiera escuchar al evento OnEmptyHealth del Damageable

Para esto creé una clase abstracta, llamada DieBehaviour, que tuviera la lógica de:

  • Requerir que el game object en el que se encuentra el script tenga el componente Damageable (DieBehaviour linea 3)
  • Obtener el componente Damageable para poder suscribirme al evento OnEmptyHealth mas adelante (DieBehaviour línea 9)
  • Suscribir y des suscribirse al evento cuando el script o el gameObject en el que esté sea habilitado o deshabilitado (DieBehaviour línea 11 a 18)
  • Y declarar un método abstracto Die, para que quien implemente la clase lo sobre escriba

Y ya con esa clase abstracta como plano, cree el script “DestroyOnDeath” que destruye al gameObject cuando muere, aquí está el código

La idea de esto es que ahora que quiera crear una lógica especial para cuando un GameObject que sea Damageable “muera” basta con crear un script que herede la clase DieBehaviour, agregarle la lógica que quiera en el método Die y ya

Ahora puedo agregar y mezclando diferentes o/y multiples comportamientos a la muerte de un GameObject simplemente arrastrando los scripts que vaya creando.

Por ejemplo si tuviera el siguiente catalogo de efectos que puedan suceder cuando un Damageable muera, separado cada uno en su propio script

  • invocar n cantidad de enemigos al morir,
  • darle un efecto de ceguera al jugador al morir
  • explotar al morir
  • marcar el juego como terminado al morir (si muere el jugador por ejemplo)
  • re-vivir a la entidad en otro lugar
  • darle un efecto positivo al que lo mató
  • lanzar una onda congeladora alrededor de donde muere

Podría combinarlos en diferentes enemigos y tener un enemigo que al morir explote y te de un efecto de ceguera, o uno que lance una onda congeladora al rededor y después invoque a otros 3 enemigos cuando muera.

Al final el prefab de mi Enemy quedó así por ahora:

<h3>Dañar al jugador cuando los enemigos lo toquen</h3>

Para dañar al jugador le agregué

  • un Riggidbody 2D, con gravedad 0
  • y un CircleCollider2D

Le agregué el evento OnTriggerEnter2D al script de Player para que cuando chocara con un enemigo se haga daño

Creé un script para que se escriba el nombre del GameObject cuando muere, para ver que el player pueda morir

y al GameObject Player le puse los componentes “Damageable” y “Print Message On Death”

Así quedó el player

Reto completado!

Destruccion de enemigo

Primero debemos darle una variable de salud

[SerializeField] int health = 5;

Luego en en metodo “TakeDamage” colocamos un condicional

public void TakeDamage(){
        if (health < 1){
            Destroy(gameObject); //Destruyo al enemigo 
        }
        health--;
    }

Dano hacia el jugador

  1. En Unity en “Hierachy” selecciono a “Player” y le asigno el tag Player
  2. Luego le agrego el componente “Box colider 2D” —> selecciono “Is Trigger”
  3. Despues selecciono a “Enemy” y le agrego el componente “Rigidbody 2D” —> gravity scale “0”

En el codigo del “Player” le agrego salud y el metodo TakeDamage

// Setteo la variable
[SerializeField] int health = 10;

// Metodo take damage
public void TakeDamage(){
        if (health < 1){
            print("[Engine] GAME OVER")
        }
        health--;
    }

En el codigo del “Enemy” escucho por una colision con Player y llamo su metodo TakeDamage

private void OnTriggerEnter2D(Collider2D collision){

        if (collision.CompareTag("Player")){
            collision.GetComponent<Player>().TakeDamage();
        }
    }

Primero le damos al player un rigibody2d con gravity scale en 0, lo mismo con el enemigo, luego generamos una variable [SerializeField] int HealthOfPlayer = 10;

Hacer que el enemigo mire en dirección al jugador

void Update() {
	// Obtenemos la posición
        Vector2 direcction = player.position - transform.position;
	// Calculamos el ángulo para rotar
        float angle = Mathf.Atan2(direcction.y, direcction.x) * Mathf.Rad2Deg;
        Quaternion targetRotation = Quaternion.AngleAxis(angle, Vector3.forward);
        // Asignamos la rotación
	transform.rotation = targetRotation;
	// Finalmente asemos que avance el enemigo
        transform.position += transform.right * Time.deltaTime * speed;
}

Retos: Daño del enemigo al jugador y ‘matar’ al enemigo

Solución: Daño del enemigo al jugador

  1. Cree una nueva variable en el Player llamada ‘health’, copié la misma función de ‘TakeDamage’ del objeto Enemy y la declaré en el Player y por ultimo le agregué un componente ‘Box Collider 2D’ con la opción de ‘Is trigger’ activada al Player.
    Ademas agregué una condición de ‘Destroy’ si la vida del player llega a 0.

Player.cs

public class Player : MonoBehaviour
{
    // Variable health
    public float health = 1;
    public float moveSpeed = 1.5f;

    //...

    void Update()
    {
        //...

        // Player destroy
        if (health <= 0)
        {
            Destroy(gameObject);
        }
    }

    // Método de daño
    public void TakeDamage()
    {
        health -= 1;
    }
}
  1. Copié casi la misma lógica del objeto Bullet y se la agregué al Enemy, para que cuando colisione con el objeto ‘Player’, ejecute el método de ‘TakeDamage’.
    Ademas agregué una condicional en el vector de dirección para que no sigua ‘buscando’ la posición del jugador si este es null (Destroy)

Enemy.cs

public class Enemy : MonoBehaviour
{
    //...

    void Update()
    {
        // Si el player todavía existe.
        if (playerPosition != null)
        {
            Vector2 direction = playerPosition.position - transform.position;
            transform.position += (Vector3)direction * speed * Time.deltaTime;
        }
    }

    // Método de colisión.
    private void OnTriggerEnter2D(Collider2D collision)
    {
        if (collision.GetComponent<Player>()) {
            collision.GetComponent<Player>().TakeDamage();
        }
    }

    //...
}

‘Matar’ al enemigo

Para esto simplemente cree una condicional de que si la variable ‘health’ llega a 0, este objeto se destruye.

Enemy.cs

public class Enemy : MonoBehaviour
{
    //...

    void Update()
    {
        //...

        // Enemy destroy
        if (health <= 0)
        {
            Destroy(gameObject);
        }
    }

    //...
}

Bonus

Para normalizar la velocidad del objeto Enemy y se acerque al objeto Player a una velocidad constante, simplemente podemos ejecutar el método ‘normalized’ al vector de dirección (direction), y así ya no se ralentizará gradualmente cuando se acerca al objeto Player.

Enemy.cs

//...

public class Enemy : MonoBehaviour
{
    //...

    void Update()
    {
        // Vector direction
        Vector2 direction = player.position - transform.position;

        // Following
        transform.position += (Vector3)direction.normalized * speed * Time.deltaTime;
    }

    //...
}

muy buena explicacion se entiende todo

Antes de llegar a este vídeo ya había hecho los retos D:
Me gusta mucho este curso.

Destrucción del Enemigo por las Balas

En OnTriggerEnter2D, comparo si es el enemigo y si lo es, le hago daño al enemigo y destruyo la bala.

    void OnTriggerEnter2D(Collider2D collider)
    {
        if (collider.CompareTag("Enemy"))
        {
            EnemyBehaviour enemy = collider.GetComponent<EnemyBehaviour>();
            enemy.TakeDamage(Damage);
            BulletPooler.sharedInstance.DestroyBullet(this);
        }
    }

Cada bala tiene una variable daño que es el daño que produce la arma (Aparte de lo enseñado en el cur hasta ahora, también creé un script Weapon).

    public int Damage
    {
        get => Weapon.Damage;
    }
    public WeaponBehaviour Weapon { get; set; }

Y Take Damage resta el daño pasado a la vida. Para eso tengo una propiead Health

    private int health;
    public int Health
    {
        get => health;
        set
        {
            health = value;
            if (health <= 0)
            {
                Die();
            }
        }
    }

Daño del Enemigo al jugador

Tengo una función Attack que le quita vida al jugador.

    public void Attack()
    {
        if (CanAttack && Player != null)
        {
            CanAttack = false;
            Player.TakeDamage(10);
            StartCoroutine(WaitAttack());
        }
        else if (Player == null)
        {
            state = State.Wander;
        }
    }

    public IEnumerator WaitAttack()
    {
        yield return new WaitForSeconds(1.0f);
        CanAttack = true;
    }

Genial