Notice: This page requires JavaScript to function properly.
Please enable JavaScript in your browser settings or update your browser.
Aprenda Estado de Corrida | Comportamento do Inimigo
Jogo de Luta no Unity
course content

Conteúdo do Curso

Jogo de Luta no Unity

Jogo de Luta no Unity

1. Sistema de Animação do Unity
2. Comportamento do Jogador
3. Comportamento do Inimigo
4. Melhore o Jogo
5. Melhore o Jogo Flappy Bird

book
Estado de Corrida

public abstract class State
{
    public bool isStateFinished;

    public abstract void StartState();
    public virtual void UpdateState()
    {
    }
    public abstract void EndState();
    public virtual void FinishState()
    {
        isStateFinished = true;
    }
}

Alterações e Adições

Variável isStateFinished:

Variável booleana que indica se o estado finalizou sua execução.

Método FinishState:

Novo método virtual que define isStateFinished como true. Por ser virtual, permite que classes derivadas sobrescrevam este método caso precisem executar ações adicionais ao finalizar um estado.

Por que essas alterações foram feitas

As alterações introduzem a variável isStateFinished para rastrear a conclusão do estado e o método FinishState para padronizar o sinal de término do estado, permitindo que classes derivadas adicionem lógica personalizada ao finalizar o estado.

Estado de Corrida

public class RunState : State
{
    Rigidbody2D rb;
    Animator animator;
    Transform player;
    float speed;
    Vector2 scale;
    Vector2 velocity;

    public RunState(Rigidbody2D rb, Animator animator, Transform p, float speed)
    {
        this.animator = animator;
        player = p;
        this.speed = speed;
        this.rb = rb;
        scale = rb.transform.localScale;
        velocity = new Vector2();
    }

    public override void StartState()
    {
        isStateFinished = false;
        animator.SetBool("run", true);
    }

    public override void UpdateState(float DeltaTime)
    {
        scale.x = rb.position.x > player.position.x ? -1 : 1;
        rb.transform.localScale = scale;

        velocity.x = scale.x * speed;
        rb.velocity = velocity;
    }

    public override void EndState()
    {
        animator.SetBool("run", false);
    }
}

Vamos analisar a classe RunState, que herda da classe State. Esta classe é responsável por gerenciar o comportamento de corrida do inimigo. O foco será nas adições e alterações feitas nesta classe.

Construtor:

public RunState(Rigidbody2D rb, Animator animator, Transform p, float speed);

Este construtor inicializa o RunState com os componentes necessários: um Rigidbody2D para movimentação, um Animator para animações, um Transform para rastrear o jogador e uma speed para definir a velocidade de corrida do inimigo;

Método StartState:

public override void StartState(); Este método define isStateFinished como false e ativa a animação de corrida ao definir o parâmetro booleano "run" no animator como true.

Método UpdateState:

public override void UpdateState(float DeltaTime); Este método atualiza a posição e orientação do inimigo com base na posição do jogador; Ajusta a escala do inimigo para que ele fique voltado para o jogador, calcula a velocidade de acordo com o valor de speed e aplica essa velocidade ao Rigidbody2D.

Método EndState:

public override void EndState() Este método interrompe a animação de corrida ao definir o parâmetro booleano "run" no animator como false.

Funcionamento para o Inimigo

  • Movimentação e Animação: Utilizando Rigidbody2D e Animator, o RunState garante que o inimigo se mova suavemente e apresente animações correspondentes. Isso torna o comportamento visual e fisicamente realista;

  • Rastreamento da Posição do Jogador: O transform player permite que o inimigo sempre se mova em direção ao jogador, o que é essencial para comportamentos de perseguição ou fuga;

  • Controle de Direção: Ajustar o scale.x com base na posição do jogador garante que o inimigo fique voltado corretamente para o jogador enquanto corre, aumentando o realismo;

  • Atualizações Dinâmicas de Estado: O método UpdateState é chamado a cada frame para ajustar continuamente o movimento e a direção do inimigo com base na posição do jogador, tornando o inimigo responsivo e dinâmico.

Inicialização do Inimigo

private void Start()
{
    idle = new IdleState(animator);
    runState = new RunState(GetComponent<Rigidbody2D>(), animator, player, speed);
    stateManager = new StateManager(idle);

    FarAwayTransition = new Transition(() =>
    {
        return (ThresholdDistance < Vector2.Distance(transform.position, player.position));
    }, new StatePourcentage(runState, 50f), new StatePourcentage(dashState, 50f));

    toIdleTransition = new Transition(() =>
    {
        return stateManager.GetCurrentState().isStateFinished;
    }, new StatePourcentage(idle, 100));

    finishRunning = new Transition(() =>
    {
        return (ThresholdDistance >= Vector2.Distance(transform.position, player.position));
    }, new StatePourcentage(idle, 100));

    stateManager.AddStateTransition(idle, FarAwayTransition);
    stateManager.AddStateTransition(dashState, toIdleTransition);
    stateManager.AddStateTransition(runState, finishRunning);
}

Explicação

Inicialização de Estado:

As variáveis idle e runState são inicializadas com seus respectivos estados. A variável idle é uma instância de IdleState com o animator passado como parâmetro, enquanto runState é uma instância de RunState que inclui um Rigidbody2D, um Animator, um Transform para o jogador e um valor de velocidade.

Inicialização do StateManager:

stateManager = new StateManager(idle); O StateManager é inicializado com o estado idle como estado inicial.

Definições de Transição:

  • FarAwayTransition: FarAwayTransition = new Transition(() => { return (ThresholdDistance < Vector2.Distance(transform.position, player.position)); }, new StatePourcentage(runState, 50f), new StatePourcentage(dashState, 50f));; Esta transição verifica se o jogador está mais distante que ThresholdDistance;

  • toIdleTransition: toIdleTransition = new Transition(() => { return stateManager.GetCurrentState().isStateFinished; }, new StatePourcentage(idle, 100)); Esta transição verifica se o estado atual foi finalizado. Se verdadeiro, transita para o estado idle com 100% de probabilidade.

  • finishRunning: finishRunning = new Transition(() => { return (ThresholdDistance >= Vector2.Distance(transform.position, player.position)); }, new StatePourcentage(idle, 100)); Esta transição verifica se o jogador está mais próximo que ThresholdDistance. Se verdadeiro, transita para o estado idle com 100% de probabilidade.

Adicionando Transições ao StateManager:

stateManager.AddStateTransition(idle, FarAwayTransition);
stateManager.AddStateTransition(dashState, toIdleTransition);
stateManager.AddStateTransition(runState, finishRunning);

Essas linhas adicionam as transições definidas ao stateManager.

Por Que Fizemos Desta Forma

Mudanças Dinâmicas de Estado:

As transições permitem que o inimigo altere seu comportamento dinamicamente com base na posição do jogador e no status de conclusão do estado atual, tornando o inimigo mais responsivo e interativo dentro do ambiente do jogo.

Transições Condicionais:

O uso de condições (como verificação de distância ou conclusão de estado) garante que as transições de estado ocorram de maneira lógica e apropriada, aumentando o realismo da jogabilidade.

Transições Baseadas em Probabilidade:

O uso de StatePourcentage permite transições baseadas em probabilidade, adicionando um elemento de imprevisibilidade e variedade ao comportamento do inimigo.

question mark

O que acontece com o animator quando o método StartState é chamado na classe RunState?

Select the correct answer

Tudo estava claro?

Como podemos melhorá-lo?

Obrigado pelo seu feedback!

Seção 3. Capítulo 5

Pergunte à IA

expand

Pergunte à IA

ChatGPT

Pergunte o que quiser ou experimente uma das perguntas sugeridas para iniciar nosso bate-papo

course content

Conteúdo do Curso

Jogo de Luta no Unity

Jogo de Luta no Unity

1. Sistema de Animação do Unity
2. Comportamento do Jogador
3. Comportamento do Inimigo
4. Melhore o Jogo
5. Melhore o Jogo Flappy Bird

book
Estado de Corrida

public abstract class State
{
    public bool isStateFinished;

    public abstract void StartState();
    public virtual void UpdateState()
    {
    }
    public abstract void EndState();
    public virtual void FinishState()
    {
        isStateFinished = true;
    }
}

Alterações e Adições

Variável isStateFinished:

Variável booleana que indica se o estado finalizou sua execução.

Método FinishState:

Novo método virtual que define isStateFinished como true. Por ser virtual, permite que classes derivadas sobrescrevam este método caso precisem executar ações adicionais ao finalizar um estado.

Por que essas alterações foram feitas

As alterações introduzem a variável isStateFinished para rastrear a conclusão do estado e o método FinishState para padronizar o sinal de término do estado, permitindo que classes derivadas adicionem lógica personalizada ao finalizar o estado.

Estado de Corrida

public class RunState : State
{
    Rigidbody2D rb;
    Animator animator;
    Transform player;
    float speed;
    Vector2 scale;
    Vector2 velocity;

    public RunState(Rigidbody2D rb, Animator animator, Transform p, float speed)
    {
        this.animator = animator;
        player = p;
        this.speed = speed;
        this.rb = rb;
        scale = rb.transform.localScale;
        velocity = new Vector2();
    }

    public override void StartState()
    {
        isStateFinished = false;
        animator.SetBool("run", true);
    }

    public override void UpdateState(float DeltaTime)
    {
        scale.x = rb.position.x > player.position.x ? -1 : 1;
        rb.transform.localScale = scale;

        velocity.x = scale.x * speed;
        rb.velocity = velocity;
    }

    public override void EndState()
    {
        animator.SetBool("run", false);
    }
}

Vamos analisar a classe RunState, que herda da classe State. Esta classe é responsável por gerenciar o comportamento de corrida do inimigo. O foco será nas adições e alterações feitas nesta classe.

Construtor:

public RunState(Rigidbody2D rb, Animator animator, Transform p, float speed);

Este construtor inicializa o RunState com os componentes necessários: um Rigidbody2D para movimentação, um Animator para animações, um Transform para rastrear o jogador e uma speed para definir a velocidade de corrida do inimigo;

Método StartState:

public override void StartState(); Este método define isStateFinished como false e ativa a animação de corrida ao definir o parâmetro booleano "run" no animator como true.

Método UpdateState:

public override void UpdateState(float DeltaTime); Este método atualiza a posição e orientação do inimigo com base na posição do jogador; Ajusta a escala do inimigo para que ele fique voltado para o jogador, calcula a velocidade de acordo com o valor de speed e aplica essa velocidade ao Rigidbody2D.

Método EndState:

public override void EndState() Este método interrompe a animação de corrida ao definir o parâmetro booleano "run" no animator como false.

Funcionamento para o Inimigo

  • Movimentação e Animação: Utilizando Rigidbody2D e Animator, o RunState garante que o inimigo se mova suavemente e apresente animações correspondentes. Isso torna o comportamento visual e fisicamente realista;

  • Rastreamento da Posição do Jogador: O transform player permite que o inimigo sempre se mova em direção ao jogador, o que é essencial para comportamentos de perseguição ou fuga;

  • Controle de Direção: Ajustar o scale.x com base na posição do jogador garante que o inimigo fique voltado corretamente para o jogador enquanto corre, aumentando o realismo;

  • Atualizações Dinâmicas de Estado: O método UpdateState é chamado a cada frame para ajustar continuamente o movimento e a direção do inimigo com base na posição do jogador, tornando o inimigo responsivo e dinâmico.

Inicialização do Inimigo

private void Start()
{
    idle = new IdleState(animator);
    runState = new RunState(GetComponent<Rigidbody2D>(), animator, player, speed);
    stateManager = new StateManager(idle);

    FarAwayTransition = new Transition(() =>
    {
        return (ThresholdDistance < Vector2.Distance(transform.position, player.position));
    }, new StatePourcentage(runState, 50f), new StatePourcentage(dashState, 50f));

    toIdleTransition = new Transition(() =>
    {
        return stateManager.GetCurrentState().isStateFinished;
    }, new StatePourcentage(idle, 100));

    finishRunning = new Transition(() =>
    {
        return (ThresholdDistance >= Vector2.Distance(transform.position, player.position));
    }, new StatePourcentage(idle, 100));

    stateManager.AddStateTransition(idle, FarAwayTransition);
    stateManager.AddStateTransition(dashState, toIdleTransition);
    stateManager.AddStateTransition(runState, finishRunning);
}

Explicação

Inicialização de Estado:

As variáveis idle e runState são inicializadas com seus respectivos estados. A variável idle é uma instância de IdleState com o animator passado como parâmetro, enquanto runState é uma instância de RunState que inclui um Rigidbody2D, um Animator, um Transform para o jogador e um valor de velocidade.

Inicialização do StateManager:

stateManager = new StateManager(idle); O StateManager é inicializado com o estado idle como estado inicial.

Definições de Transição:

  • FarAwayTransition: FarAwayTransition = new Transition(() => { return (ThresholdDistance < Vector2.Distance(transform.position, player.position)); }, new StatePourcentage(runState, 50f), new StatePourcentage(dashState, 50f));; Esta transição verifica se o jogador está mais distante que ThresholdDistance;

  • toIdleTransition: toIdleTransition = new Transition(() => { return stateManager.GetCurrentState().isStateFinished; }, new StatePourcentage(idle, 100)); Esta transição verifica se o estado atual foi finalizado. Se verdadeiro, transita para o estado idle com 100% de probabilidade.

  • finishRunning: finishRunning = new Transition(() => { return (ThresholdDistance >= Vector2.Distance(transform.position, player.position)); }, new StatePourcentage(idle, 100)); Esta transição verifica se o jogador está mais próximo que ThresholdDistance. Se verdadeiro, transita para o estado idle com 100% de probabilidade.

Adicionando Transições ao StateManager:

stateManager.AddStateTransition(idle, FarAwayTransition);
stateManager.AddStateTransition(dashState, toIdleTransition);
stateManager.AddStateTransition(runState, finishRunning);

Essas linhas adicionam as transições definidas ao stateManager.

Por Que Fizemos Desta Forma

Mudanças Dinâmicas de Estado:

As transições permitem que o inimigo altere seu comportamento dinamicamente com base na posição do jogador e no status de conclusão do estado atual, tornando o inimigo mais responsivo e interativo dentro do ambiente do jogo.

Transições Condicionais:

O uso de condições (como verificação de distância ou conclusão de estado) garante que as transições de estado ocorram de maneira lógica e apropriada, aumentando o realismo da jogabilidade.

Transições Baseadas em Probabilidade:

O uso de StatePourcentage permite transições baseadas em probabilidade, adicionando um elemento de imprevisibilidade e variedade ao comportamento do inimigo.

question mark

O que acontece com o animator quando o método StartState é chamado na classe RunState?

Select the correct answer

Tudo estava claro?

Como podemos melhorá-lo?

Obrigado pelo seu feedback!

Seção 3. Capítulo 5
some-alt