unity,

Exemplo do Design Pattern Command na Unity com C#

Bruno Cicanci Bruno Cicanci Seguir 29 de Dezembro de 2020 · 4 min de leitura
Exemplo do Design Pattern Command na Unity com C#
Compartilhe

Sempre recomendo o livro Game Programming Patterns, que possui versões física e digital à venda, além de uma online gratuita disponibilizada pelo autor, Robert Nystrom. Este livro revisita os design patterns definidos na década de 1990 pela “Gangue dos Quatro”, focando no seu uso para o desenvolvimento de jogos.

O livro conta com excelentes exemplos e com pseudocódigo baseado em C/C++, além de descreve situações em que cada programming pattern pode ser utilizado. Já realizei algumas palestras sobre este assunto e utilizei este livro como base, sendo a mais recente na TDC Porto Alegre 2019. Meu objetivo com este post e, com os próximos que virão, é criar exemplos do uso de cada programming pattern na game engine Unity e com a linguagem de programação C#.

Seguindo a ordem do livro, este primeiro post será sobre o Design Pattern Command. O código deste exemplo, assim como de todos os próximos, pode ser acessado neste repositório do GitHub. Os demais posts desta série podem ser acessados neste link.

Design Pattern Command

O Command é um design pattern que tem como objetivo encapsular um método ou ação. Em uma definição muito simples pode-se dizer que é um padrão para callbacks. Um exemplo bem prático do Command é o input de um jogo. Imagine que seu jogo possui uma opção para que o jogador modifique as ações de cada botão, seja por preferencia pessoal ou acessibilidade. Com a Implementação do Command fica simples modificar o comando que um botão executa, como demonstrado no exemplo a seguir.

Implementação na Unity com C#

Neste exemplo de implementação existem duas ações possíveis para o jogador: Pular e Atirar. Para simplificar o exemplo, cada ação será apenas uma mensagem de log. O código abaixo define exatamente isso, dois comandos que podem ser executados. É importante ter uma interface neste caso, ou pelo menos uma classe base, para que o código que executar estas ações não precise necessariamente saber o tipo de cada classe derivada.

public interface ICommand
{
    void Execute();
}

public class JumpCommand : ICommand
{
    public void Execute()
    {
        Debug.Log("Execute command: Jump");
    }
}

public class FireCommand : ICommand
{
    public void Execute()
    {
        Debug.Log("Execute command: Fire");
    }
}

E é basicamente isso, uma interface com o método que executará uma ação e duas implementações desta interface. Agora ambas ações podem ser utilizadas em outra classe, como será demonstrado no MonoBehaviour abaixo. A classe abaixo possui dois métodos públicos executados por botões na Unity, o ButtonA() e o ButtonB(). Estes métodos executam qualquer comando associado com as respectivas variáveis, as quais possuem o tipo da interface ICommand.

public class DesignPatternCommand : MonoBehaviour
{
    private ICommand _buttonA;
    private ICommand _buttonB;

    private void Start()
    {
      _buttonA = new JumpCommand();
      _buttonB = new FireCommand();
    }

    public void ButtonA()
    {
        _buttonA.Execute();
    }

    public void ButtonB()
    {
        _buttonB.Execute();
    }
}

Quando executado, o código acima irá atribuir a ação de pular para o botão A e a ação de atirar para o botão B. Agora imagine que, neste exemplo, teremos uma opção que permite o jogador inverter os comandos dos botões. Para isso, um método como este abaixo irá alterar o comando dos botões sem a necessidade de qualquer outra modificação no código.

private void ChangeButtons()
{
  _buttonA = new FireCommand();
  _buttonB = new JumpCommand();
}

Este é um exemplo bem simples para explicar o conceito por trás deste programming pattern. A partir disso pode-se ver como o Command é um poderoso recurso para todo programador, pois permite alterar ações sem criar dependências no código. Existem outros exemplos interessantes para o seu uso, como um sistema de avançar e voltar no tempo onde todas as ações do jogador podem ser uma lista de comandos executados. Isso pode ser utilizado até mesmo em um editor para desfazer e refazer uma determinada ação.

Exemplo

Neste repositório do GitHub existe um exemplo utilizando o código acima, porém com 4 botões de ações do jogador e um outro botão que permite embaralhar as ações.

Design Pattern Command

O Command é um padrão simples, mas que é muito poderoso quando entendido e utilizado corretamente na arquitetura de um jogo. Imagine ter que adicionar novos botões no exemplo acima, ou um hardware diferente para o input. Tudo isso pode ser feito de forma prática com o Command. Este programming pattern é um bom aliado para tornar um jogo mais acessível, permitindo a customização do controle do jogo pelo jogador.

Gostou do post?
Como muitos programadores, aprecio um bom café. Se curtiu este conteúdo, que tal me presentear com um café?
Bruno Cicanci
Escrito por Bruno Cicanci Seguir
Bacharel em Ciência da Computação e pós-graduado em Produção e Programação de Jogos. Atuo profissionalmente com desenvolvimento de jogos desde 2010. Já trabalhei na Glu Mobile, Electronic Arts, 2Mundos, Aquiris, e atualmente na Ubisoft em Londres. Escrevo neste blog desde 2009.