
Esta página explica como usar enums baseados em ScriptableObject em seu projeto do Unity.
Este é o terceiro em uma série de seis mini-guia criados para ajudar desenvolvedores em Unity com a demonstração que acompanha o e-book, Create modular game architecture in Unity with ScriptableObjects.
A demonstração é inspirada na mecânica clássica do jogo arcade de bola e raquete e mostra como os ScriptableObjects podem ajudar você a criar componentes que são testáveis, escaláveis e fáceis de usar para designers.
Juntos, o e-book, o projeto de demonstração e esses mini-guia fornecem as práticas recomendadas para usar padrões de design de programação com a classe ScriptableObject em seu projeto do Unity. Essas dicas podem ajudar você a simplificar seu código, reduzir o uso de memória e promover a reutilização do código.
Esta série inclui os seguintes artigos:
Antes de se aprofundar no projeto de demonstração de ScriptableObject e nesta série de mini-guia, lembre-se de que, no seu núcleo, os padrões de design são apenas ideias. Eles não se aplicam a todas as situações. Essas técnicas podem ajudar você a aprender novas maneiras de trabalhar com Unity e ScriptableObjects.
Cada padrão tem prós e contras. Escolha apenas aqueles que beneficiam significativamente seu projeto específico. Seus designers contam muito com o Unity Editor? Um padrão baseado em ScriptableObject pode ser uma boa opção para ajudá-los a colaborar com seus desenvolvedores.
No final das contas, a melhor arquitetura de código é aquela que se adapta ao seu projeto e à sua equipe.

Enums são uma maneira útil de gerenciar um conjunto fixo de valores nomenclados em seu código. No entanto, eles vêm com algumas limitações. Como os valores serializados de enum são armazenados como inteiros em vez de seus nomes simbólicos, remover ou reordenar um valor pode levar a comportamentos incorretos ou inesperados. Isso significa que os enums, especialmente quando você tem muitos deles, podem causar problemas no desenvolvimento do Unity.
A abordagem padrão
Veja o que parece um enum típico:
[System.Serializável]
HandGestures de enum público
{
Rock,
Papel,
Taças
}
Você pode serializar um enum com o atributo System.Serialalizable e ele aparece no Inspector.
O problema
Reorganizar ou excluir um valor pode causar problemas. Como cada valor internamente é um inteiro, o que ele representa pode se tornar algo diferente. No exemplo dado, excluir o valor Paper faria com que Scissors assumisse o valor de 1.
Ou, se adicionarmos um valor como no exemplo abaixo.
O valor de enum selecionado será alterado se ocorrer após a entrada excluída.
Isso pode causar problemas ao manter e atualizar projetos, especialmente quando seu enumeração contém vários valores. Você pode reduzir esse problema deixando um elemento em branco ou não usado, ou definindo explicitamente valores inteiros. No entanto, nenhuma solução é ideal.

Os enums baseados em ScriptableObject oferecem a funcionalidade dos enums tradicionais, mas são armazenados como assets individuais. Por exemplo, veja o PlayerIDSO ScriptableObject no projeto PaddleBallSO no exemplo abaixo.
Essencialmente, esse é um ScriptableObject em branco.
Você pode usar isso para criar diversos assets de ScriptableObject no projeto, como P1, P2 etc. Mesmo quando não contêm dados, você pode usar ScriptableObjects para comparação. Basta criar um asset ScriptableObject no projeto e dar um nome.
Você pode criar quantos IDs de jogador precisar dentro do projeto e alternar facilmente entre eles. Basta alterar o asset atribuído no script do GameDataSO.
Se você estiver buscando igualdade, isso funciona de maneira semelhante a uma enumeração. Duas variáveis se referem ao mesmo ScriptableObject? Em caso afirmativo, são o mesmo tipo de item. Caso contrário, não serão.
Mesmo sem nenhum dado adicional, o ScriptableObject representa uma categoria ou um tipo de item.
Em PaddleBallSO, o PlayerIDSO se torna uma designação de equipe. Usamos os assets P1 e P2 no GameDataSO para diferenciar as duas raquetes.
O script GameSetup atribui a cada raquete um ID de jogador. Durante a jogabilidade, os scripts Paddle comparam a entrada do jogador com o ID de equipe designado.
Isso tem aplicativos para qualquer tipo de jogo Multiplayer. Alternativamente, considere adotá-los onde puder acessar para um enumeração.
Como são apenas atribuições no Inspector, os ScriptableObjects não estão sujeitos aos mesmos problemas de renomeamento e reorganização.
Deseja alterar os nomes dos identificadores para “Player1” ou “Player2,”, respectivamente? Você pode fazer isso, e tudo continua funcionando. Está adicionando mais ScriptableObjects? Não é problema, a atribuição de assets no Inspector permanece a mesma.

Esse comportamento é útil para criar jogabilidade. Na demonstração de padrões, clique no botão Switch Enum para alterar as equipes. Um MonoBehaviour no DemoBall atualiza o SpriteRenderer de acordo.
A bola inflige dano a um bloco quando colida? Descubra executando um teste rápido de igualdade. Aqui está uma maneira de compará-los no exemplo de código abaixo.
Esse método pode determinar se dois GameObjects estão na mesma equipe, o que é útil ao verificar se há interações amigáveis com o inimigo. Essa comparação simples pode ser aplicada a pickups de itens, danos ou qualquer outra coisa que tenha um “equipe” ou “alinhamento”.
A parte divertida acontece quando você adiciona lógica aos seus ScriptableObjects. Diferente de uma enum convencional, um ScriptableObject pode ter campos e métodos, além de manter dados.
Use-os para que cada ScriptableObject tenha lógica de comparação especializada. Por exemplo, você pode ter um ScriptableObject que define efeitos de dano especiais (por exemplo, frio, calor, elétrico, mágico e assim por diante).
Se seu aplicativo requer um sistema de inventário para equipar itens de jogo, os ScriptableObjects podem representar tipos de itens ou slots de armas. Certos personagens não podem carregar determinados itens? Alguns itens são mágicos ou têm habilidades especiais? Enums baseados em ScriptableObject podem adicionar métodos para verificar se isso acontece.
O MonoBehaviour DemoBall no exemplo anterior inclui o método AreEqual para comparar ScriptableObjects. Ao estender o comportamento, você pode agrupar a lógica da comparaçãopor dentro do próprio ScriptableObject.
Na demonstração de padrões, você pode modificar a bola para que seja mais seletiva ao colidir com um objeto. Veja um item de uso geral para colisão no exemplo de código abaixo.
Isso poderia gerar resultados semelhantes à demonstração atual, mas agora ele tem um campo m_Weakness. Isso permite que cada ScriptableObject defina outro ScriptableObject a ser destruído na colisão.
Em vez de chamar o método AreEqual, cada ScriptableObject gerencia simplesmente sua própria lógica de comparação.
O resultado é mais flexível e extensível. Em vez de deixar que a bola destrua um bloco de uma equipe diferente, você pode ser específico. Várias bolas na cena podem destruir blocos diferentes, dependendo dos CollisionItems individuais.
Isso estabelece o palco para interações diferentes e mais complexas. Se você quisesse criar um sistema de rock-paper-scissors, poderia definir três ScriptableObjects: Pedra, papel e tesouras. Cada uma poderia ter sua própria m_Weakness e usar o método IsWinner para lidar com as interações.
Diferente de enums, os ScriptableObjects tornam esse processo modular e adaptável. Não há necessidade de depender de estruturas de dados extras ou adicionar lógica extra para sincronizar com um conjunto de dados separado. Basta adicionar um campo e/ou método adicionais para lidar com a lógica.
Depois de se familiarizar com enums baseados em ScriptableObject, você perceberá que eles podem melhorar seu fluxo de trabalho, especialmente ao trabalhar com os colegas de equipe. Como são assets, atualizá-los cria menos conflitos de mesclagem, reduzindo o risco de perda de dados.
Adicionar novas inscrições baseadas em ScriptableObject é igual a criar outro asset. Diferente de enums tradicionais, adicionar novos valores não quebrará seu código existente. Além disso, o Unity já tem ferramentas integradas para pesquisar, filtrar e organizá-las, assim como qualquer outro asset.
Como bônus, usar a UI "arrastar e soltar" do Editor permite que seus designers estendam os dados de jogabilidade sem suporte adicional de um desenvolvedor de software. Você ainda precisará coordenar como configurar os campos inicialmente, mas os designers poderão preencher esses campos com dados por conta própria.

Enumes baseados em ScriptableObject são mais um recurso que sua equipe pode usar para aumentar a colaboração e a eficiência.
Leia mais sobre padrões de design com ScriptableObjects em nosso e-book técnico Criar arquitetura de jogos modulares em Unity com ScriptableObjects. Você também pode saber mais sobre padrões de design de desenvolvimento comuns do Unity em Aumentar o nível do código com padrões de programação de jogos.