[POO] Herança na Unity

Herança é um conceito do paradigma de programação conhecido como Programação Orientada a Objetos , que tem como objetivo construir e trabalhar com abstrações de objetos do mundo real, em um nível de código. A Herança dá a capacidade de uma classe/objeto herdar comportamentos previamente definidos em outra classe, sem a necessidade de duplicação do código, permitindo a extensão e a sobrescrita de comportamentos já existentes, de acordo com a necessidade do novo objeto/classe. Para definir uma relação de herança no C#, a "palavra" reservada : (dois pontos) deve ser utilizada na definição da classe que estamos criando, indicando de qual outra classe o nosso script deve herdar. public class Jogador : MonoBehaviour { // Classe Jogador que herda da classe MonoBehaviour } Por padrão, todos os scripts criados na Unity herdam de MonoBehaviour, que é a classe base da Unity para Scripts que serão associados aos GameObjects do jogo. Embora essa definição de herança

[Melhorado] Câmera seguindo jogador - 2D

[Melhorado] Câmera seguindo o jogador em um mundo 2D

E aí, pessoal! Aproveitando o exemplo desenvolvido no post Câmera seguindo jogador - 2D, vamos fazer algumas melhorias no nosso script ControladorCamera para torná-lo mais flexível, permitindo que a câmera siga o jogador em apenas um único eixo (x ou y).

Câmera seguindo o jogador durante a movimentação
Câmera seguindo o jogador durante a movimentação

Nós vamos adicionar as seguintes funcionalidades no nosso ControladorCamera:
  • Habilitar/desabilitar movimentação no eixo X;
  • Habilitar/desabilitar movimentação no eixo Y;
Pronto para continuar?

Vamos iniciar nossa melhoria criando uma variável para permitir habilitar/desabilitar a movimentação da câmera no eixo x (para os lados), conforme abaixo:

    /// <summary>
    /// TRUE se a câmera deve seguir o jogador no
    /// eixo X (para os lados) e FALSE caso contrário
    /// </summary>
    [SerializeField]
    private bool moverX;

A variável moverX determina se a câmera deve acompanhar o jogador durante as movimentações para esquerda e para a direita (eixo x). Para que isso funcione, precisamos alterar também o método FixedUpdate para verificar a situação da variável moverX antes de realizar a movimentação da câmera.

A alteração da movimentação no método FixedUpdate será realizada para implementar a seguinte lógica:
  • Se moverX = false, o valor do eixo x da variável que representa a posição de destino da movimentação deve ser alterado para o mesmo valor do eixo x da câmera, fazendo com que nenhuma movimentação no eixo x seja necessária;
  • Se moverX = true, não precisamos fazer nada, permitindo que o código seja executado como era anteriormente.
A alteração descrita acima pode ser vista no código abaixo:

    // Posição alvo da movimentação (para onde a câmera deve mover-se)
    Vector3 posicaoAlvo = this.jogador.position;

    if (!this.moverX) {                
        posicaoAlvo.x = this.transform.position.x;
    }

Ei! Espera. Para que serve essa variável posicaoAlvo?
Opa, bem observado. Anteriormente nós estávamos utilizando diretamente a posição do jogador (this.jogador.position) como posição de destino da nossa movimentação. Certo?
Essa abordagem funcionava muito bem no exemplo anterior, porque nós não fazíamos nenhuma alteração nessa posição de destino. Porém, agora nós queremos controlar o valor do eixo x da posição de destino dependendo da situação variável moveX. Para implementarmos esse controle sem alterar diretamente a posição do jogador, nós precisamos criar uma variável temporária, que armazenará o valor calculado para a posição de destino e substituirá a posição do jogador no método Lerp. Vamos ver como isso tudo fica junto?

É importante lembrar que essa alteração deve ser realizada antes de executarmos o Lerp, já que a nova variável posicaoAlvo precisará substituir o uso da posição do jogador (this.jogador.position) durante o uso do Lerp conforme o trecho de código abaixo:

	// Calcula a posição final da câmera
	// enquanto ela se move em direção ao jogador,
	// utilizando a velocidade de movimentação definida anteriormente                        
	Vector3 posicaoFinal = Vector3.Lerp(
		this.transform.position, // Posição de origem
		posicaoAlvo, // Posição de destino
		(this.velocidadeMovimentacao * Time.deltaTime) // Passo
	);

Agora que sabemos para que serve a nova variável posicaoAlvo e sabemos como utilizá-la, vamos dar uma olhada em como ficou o nosso FixedUpdate depois dessas alterações:

    private void FixedUpdate() {        
        // Posição alvo da movimentação (para onde a câmera deve mover-se)
        Vector3 posicaoAlvo = this.jogador.position;

        if (!this.moverX) {
            posicaoAlvo.x = this.transform.position.x;
        }

        // Calcula a posição final da câmera
        // enquanto ela se move em direção ao jogador,
        // utilizando a velocidade de movimentação definida anteriormente                        
        Vector3 posicaoFinal = Vector3.Lerp(
            this.transform.position, // Posição de origem
            posicaoAlvo, // Posição de destino
            (this.velocidadeMovimentacao * Time.deltaTime) // Passo
        );

        // Mantém a câmera na mesma posição Z, para continuar
        // visualizando os objetos do jogo
        posicaoFinal.z = this.transform.position.z;
        // Move a câmera para a nova posição
        this.transform.position = posicaoFinal;        
    }

Ao adicionar a nova variável moverX, uma nova opção aparecerá no Inspector, no script ControladorCamera enquanto a câmera estiver selecionada, permitindo marcar e desmarcar, ou seja, habilitar e desabilitar a movimentação da câmera no eixo X.

ControladorCamera no Inspector com nova variável moverX
ControladorCamera no Inspector com nova variável moverX


O resultado da nossa alteração no ControladorCamera com a opção moverX desativada permite que a câmera continue seguindo o jogador no eixo y (para cima e para baixo), enquanto mantém a câmera estática no eixo x.

Câmera seguindo o jogador apenas no eixo y
Câmera seguindo o jogador apenas no eixo y

Para habilitar novamente a movimentação no eixo x, basta marcarmos a opção moverX no Inspector.

ControladorCamera no Inspector com nova variável moverX
ControladorCamera no Inspector com nova variável moverX


Com a variável moverX marcada novamente, o ControladorCamera volta a seguir o jogador em ambos os eixos (x e y), permitindo que a movimentação no eixo x seja habilitada/desabilitada em momentos direferens do jogo, de acordo com a mecânica desejada.

Câmera seguindo o jogador nos eixos x e y
Câmera seguindo o jogador nos eixos x e y

Usando a alteração que fizemos para habilitar/desabilitar a movimentação no eixo x como base, podemos facilmente fazer a mesma alteração para controlar a movimentação no eixo y.

Primeiro, vamos criar uma variável para habilitar/desabilitar a movimentação da câmera no eixo y.

    /// <summary>
    /// TRUE se a câmera deve seguir o jogador no
    /// eixo Y (para cima e para baixo) e FALSE caso contrário
    /// </summary>
    [SerializeField]
    private bool moverY;

Em seguida, vamos adicionar a condição para verificar a situação da variável moverY e permitir ou bloquear a movimentação da câmera no eixo y da mesma forma que fizemos com o eixo x.

    if (!this.moverY) { 
        posicaoAlvo.y = this.transform.position.y;
    }

Juntando tudo com o código já existente, temos o seguindo código no nosso FixedUpdate, já controlando a movimentação dos eixos x e y. Simples, né?

    private void FixedUpdate() {        
        // Posição alvo da movimentação (para onde a câmera deve mover-se)
        Vector3 posicaoAlvo = this.jogador.position;

        if (!this.moverX) {
            posicaoAlvo.x = this.transform.position.x;
        }

        if (!this.moverY) {                
            posicaoAlvo.y = this.transform.position.y;
        }

        // Calcula a posição final da câmera
        // enquanto ela se move em direção ao jogador,
        // utilizando a velocidade de movimentação definida anteriormente                        
        Vector3 posicaoFinal = Vector3.Lerp(
            this.transform.position, // Posição de origem
            posicaoAlvo, // Posição de destino
            (this.velocidadeMovimentacao * Time.deltaTime) // Passo
        );

        // Mantém a câmera na mesma posição Z, para continuar
        // visualizando os objetos do jogo
        posicaoFinal.z = this.transform.position.z;
        // Move a câmera para a nova posição
        this.transform.position = posicaoFinal;        
    }

Mais uma vez, temos uma nova variável aparecendo no Inspector do ControladorCamera, dessa vez é a variável moverY para habilitar/desabitar a movimentação da câmera no eixo y (para cima e para baixo).

ControladorCamera no Inspector com nova variável moverY
ControladorCamera no Inspector com nova variável moverY

Com essa alteração, agora podemos habilitar/desabilitar a movimentação em ambos os eixos x e y, tornando a configuração da câmera mais flexível, permitindo que a câmera se comporte de uma forma diferente em momentos distintos do jogo.
O resultado da movimentação no eixo x, para os lados, habilitada e a do eixo y, para cima e para baixo,  desabilitada e o script  completo do ControladorCamera podem ser vistos abaixo:

Câmera seguindo o jogador apenas no eixo x
Câmera seguindo o jogador apenas no eixo x

Script ControladorCamera completo:
public class ControladorCamera : MonoBehaviour
{

    /// <summary>
    /// Transform do jogador que será seguido pela câmera
    /// </summary>
    [SerializeField]
    private Transform jogador;

    /// <summary>
    /// TRUE se a câmera deve seguir o jogador no
    /// eixo X (para os lados) e FALSE caso contrário
    /// </summary>
    [SerializeField]
    private bool moverX;

    /// <summary>
    /// TRUE se a câmera deve seguir o jogador no
    /// eixo Y (para cima e para baixo) e FALSE caso contrário
    /// </summary>
    [SerializeField]
    private bool moverY;

    /// <summary>
    /// Velocidade de movimentação da câmera para seguir o jogador
    /// </summary>
    [SerializeField]
    private float velocidadeMovimentacao;



    private void FixedUpdate() {        
        // Posição alvo da movimentação (para onde a câmera deve mover-se)
        Vector3 posicaoAlvo = this.jogador.position;

        if (!this.moverX) {
            posicaoAlvo.x = this.transform.position.x;
        }

        if (!this.moverY) {                
            posicaoAlvo.y = this.transform.position.y;
        }

        // Calcula a posição final da câmera
        // enquanto ela se move em direção ao jogador,
        // utilizando a velocidade de movimentação definida anteriormente                        
        Vector3 posicaoFinal = Vector3.Lerp(
            this.transform.position, // Posição de origem
            posicaoAlvo, // Posição de destino
            (this.velocidadeMovimentacao * Time.deltaTime) // Passo
        );

        // Mantém a câmera na mesma posição Z, para continuar
        // visualizando os objetos do jogo
        posicaoFinal.z = this.transform.position.z;
        // Move a câmera para a nova posição
        this.transform.position = posicaoFinal;        
    }
}


Como de costume, o projeto desenvolvido para este post pode ser baixado aqui.

O que achou? Deixe o seu comentário com dúvidas e sugestões. Até a próxima! o/

Comentários

Postagens mais visitadas deste blog

Transição de Fases (navegação entre Cenas) na Unity

GetComponent - Obtendo a referência para outros componentes do GameObject

[POO] Herança na Unity