Menu
CoddyTech

Um script base de inimigo

Parte da seção Arquitetura de Jogos no Unity do Journey de Unity da Coddy. Lição 2 de 64.

Em C#, uma classe pode herdar de outra: class Ghost : Enemy obtém todos os campos e métodos de Enemy e adiciona os próprios. Um método que a classe base marca como virtual pode ser substituído na subclasse com override, e base.Describe() executa a versão da classe base de dentro da nova. Em C# puro:

class Enemy
{
    protected int hp = 3;

    public virtual string Describe()
    {
        return "Enemy with " + hp + " hp";
    }
}

class Ghost : Enemy
{
    public override string Describe()
    {
        return base.Describe() + ", see-through";
    }
}

O Describe() de Ghost retorna Enemy with 3 hp, see-through. protected significa que Enemy e suas subclasses podem usar hp, mas outras classes não podem.

No Unity, os inimigos compartilham a maior parte do código: pontos de vida, uma velocidade e uma maneira de se mover. Esse código fica em uma classe base que herda de MonoBehaviour, e cada tipo de inimigo herda dela. Este Enemy define seus pontos de vida em Start e caminha na direção para a qual está voltado em Update, enquanto um Ghost altera a inicialização para se mover duas vezes mais rápido:

public class Enemy : MonoBehaviour
{
    public int maxHp = 3;
    public float speed = 2f;
    protected int hp;

    protected virtual void Start()
    {
        hp = maxHp;
    }

    protected virtual void Update()
    {
        transform.Translate(Vector3.forward * speed * Time.deltaTime);
    }
}
public class Ghost : Enemy
{
    protected override void Start()
    {
        base.Start();
        speed *= 2f;
    }
}

Ghost herda os campos, então o Inspector mostra maxHp e speed em um Ghost. Ele também herda Update, então caminha sem ter um Update próprio. hp é protected: Enemy e suas subclasses podem usá-lo, mas outros scripts não podem.

O Unity encontra Start e Update pelo nome, independentemente do nível de acesso, e chama o método da classe mais derivada. Se o Start de Enemy fosse um void Start() private e Ghost declarasse o próprio, o Unity chamaria somente o de Ghost: o de Enemy nunca seria executado, e hp permaneceria em 0 sem nenhum erro. Declarar as mensagens da classe base como protected virtual deixa isso claro em C#: a subclasse escreve override, e base.Start() executa a parte da classe base no ponto em que você o chama. Não inclua a chamada e essa parte da classe base será ignorada; é assim que uma subclasse substitui uma etapa em vez de acrescentar algo a ela.

challenge icon

Desafio

Fácil

Faça com que Golem e Wasp executem a parte de Enemy antes da própria.

  1. Em Enemy, escreva protected virtual antes de void Start() e void Update().
  2. Em Golem, use protected override void Start(), com base.Start(); como primeira linha.
  3. Em Wasp, use protected override void Update(), com base.Update(); como primeira linha.

Pressione “Jogar”: o golem marcha com hp cheio, e a vespa ziguezagueia enquanto marcha. Em seguida, pressione “Verificar”.

Experimente você mesmo

using UnityEngine;

// O que todos os monstros têm em comum.
public class Enemy : MonoBehaviour
{
    public int maxHp = 4;
    public float speed = 1.5f;

    protected int hp;
    protected Vector3 spawnPoint;

    void Start()
    {
        hp = maxHp;
        spawnPoint = transform.position;
    }

    void Update()
    {
        // avance em direção ao castelo, ao longo do eixo z
        transform.position += Vector3.back * speed * Time.deltaTime;
    }
}

Todas as lições de Arquitetura de Jogos no Unity

Pratique por conta própria: Playground de Unity