
Comece com a demonstração de ScriptableObjects do Unity
Esta página fornece uma visão geral de PaddleBallSO, o projeto de demonstração acompanhante do e-book Criar arquitetura de jogo modular no Unity com ScriptableObjects, e explica como ele utiliza padrões de design e modularidade em sua arquitetura de código.
Este é o primeiro de uma série de seis mini-guias criadas para ajudar desenvolvedores do Unity com a demonstração que acompanha o e-book. A demonstração é inspirada na mecânica clássica de jogos de arcade de bola e raquete, e mostra como os ScriptableObjects podem ajudá-lo a criar componentes que são testáveis, escaláveis e amigáveis para designers.
Juntos, o e-book, o projeto de demonstração e estas mini-guias fornecem as melhores práticas para usar padrões de design de programação com a classe ScriptableObject em seu projeto Unity. Essas dicas podem ajudá-lo a simplificar seu código, reduzir o uso de memória e promover a reutilização de código.
Esta série inclui os seguintes artigos:
Nota importante antes de começar
Antes de você mergulhar no projeto de demonstração ScriptableObject e nesta série de mini-guias, lembre-se de que, em sua essência, os padrões de design são apenas ideias. Eles não se aplicam a todas as situações. Essas técnicas podem ajudá-lo 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 dependem muito do Editor do Unity? Um padrão baseado em ScriptableObject pode ser uma boa escolha para ajudá-los a colaborar com seus desenvolvedores.
No final, a melhor arquitetura de código é aquela que se adapta ao seu projeto e equipe.

O projeto ScriptableObject da bola de raquete
O PaddleBallSO gira em torno do jogo clássico que deu origem aos videogames modernos, apresentando dois jogadores, duas raquetes e uma bola.
A ênfase aqui está na infraestrutura, em vez de mecânicas de jogo. Pense nisso como "encanamento de jogo" – a base menos glamourosa, mas vitais que mantém sua aplicação funcionando.
Este projeto foca em como ScriptableObjects podem trabalhar nos bastidores para construir uma aplicação unificada. Use-os para construir sistemas de jogo versáteis que podem simplificar a manutenção do projeto e promover a reutilização de código. Você também pode usá-los para dados de jogadores, gerenciamento de estado do jogo, comportamentos dentro do jogo e mais.
O projeto PaddleBallSO é compatível com a versão mais recente do Unity Long Term Support (LTS), atualmente 2022 LTS. Ele incorpora o UI Toolkit para criar UI em tempo de execução e o Input System para lidar com entradas do usuário.

Conceitos básicos
Localize e baixe o projeto no repositório do GitHub.
Carregue a Bootloader_scene ou ative Load Bootstrap Scene on Play no menu GameSystems. Entre no modo Play para começar.
Embora estes não sejam específicos para ScriptableObjects, o projeto de demonstração usa algumas técnicas comuns para ajudar a iniciar a aplicação do jogo em um estado consistente e previsível.
Um Scene Bootstrapper (ou bootloader) é um script de extensão do Editor responsável por configurar o estado inicial do jogo. Este código de inicialização é separado da lógica do jogo e garante que todas as dependências sejam configuradas corretamente para os objetos na cena.
Para evitar problemas de dependência, o bootstrapper configura objetos de jogo essenciais, gerentes ou serviços quando uma cena é carregada.
Se sua aplicação Unity abrange várias cenas, o bootloader pode forçar o carregamento de uma cena bootstrap específica, que é a primeira cena nas Configurações de Build. Ao sair do modo Play, o Editor recarrega a cena anterior.
Outro componente na cena bootstrap, o Sequence Manager, pode então instanciar Prefabs essenciais ao carregar a cena. Neste projeto de demonstração específico, tudo que é necessário para criar o jogo é um Prefab, incluindo uma câmera, SplashScreen, menus de UI e um SceneLoader.
O SceneLoader então carrega (e descarrega) aditivamente quaisquer cenas de gameplay conforme necessário. Na maioria dos casos, essas cenas são compostas principalmente de Prefabs.
Project scenes
Cada nível de mini-jogo é uma cena Unity separada e aparece nas Configurações de Build. Desative o SceneBootstrapper no menu GameSystems se você quiser explorar essas cenas individuais.
Muitos projetos também incluem uma área de preparação para o menu principal após a cena bootstrap. Este projeto de demonstração simplificado omite uma cena de menu principal.

Visão geral do projeto PaddleBallSO
Use os menus Play e Pattern para testar PaddleBallSO, que inclui:
- demonstrações de Design pattern, ou exemplos pequenos, que mostram técnicas específicas e ilustram cada padrão isoladamente.
- Mini-jogos que combinam isso em amostras funcionais e operacionais
A pasta Core contém partes do código base que não são específicas de aplicativos, como os scripts de padrão básico, gerenciamento de cena e lógica de UI. Estas são classes mais gerais que podem se aplicar a uma variedade de aplicativos.

Explorando os padrões e mini-jogo
O jogo de amostra recria uma icônica simulação de física 2D e demonstra o potencial dos padrões de design baseados em ScriptableObject.
Antes de mergulhar nos padrões, no entanto, você vai querer se familiarizar com os MonoBehaviours que compõem o aplicativo. Como você pode esperar, componentes como scripts Paddle, Ball, Bouncer e ScoreGoal governam a jogabilidade básica.
Vários scripts de gerenciador de nível superior controlam o fluxo do jogo:
- O GameManger controla os estados do jogo (início, fim, reiniciar), inicializa os componentes do jogo, gerencia a UI e responde a eventos.
- O GameSetup trabalha com o GameManager para configurar a bola, as raquetes, as paredes e os gols.
- O ScoreManager atualiza os valores de pontuação, lida com eventos do jogo e controla as atualizações da UI para exibições de pontuação.
Esses MonoBehaviours trabalham com seus ScriptableObjects. Eles desempenham um papel vital em conectar esses componentes para que possam se comunicar e compartilhar dados entre si.
Eventos são instrumentais para a comunicação entre diferentes partes do projeto. Eles conectam esses scripts de gerenciador com outros objetos de cena e a interface do usuário. Esta arquitetura orientada a eventos pode ajudar a tornar o código mais organizado e depurável.
Também fornecemos exemplos de demonstração simplificados para cada um dos padrões de ScriptableObject mais comuns. À medida que você se familiariza com eles, começará a reconhecer como os ScriptableObjects sustentam a arquitetura do mini-jogo.
Poderíamos ter feito o mini-jogo em destaque com muito menos linhas de código, mas esta demonstração foca especificamente em padrões de design com ScriptableObjects. Observe que você também pode implementar muitos desses padrões sem ScriptableObjects.
Decida em equipe como cada padrão pode se aplicar ao seu projeto e escolha a abordagem que funciona melhor para você.

Arquitetura de jogo modular
A modularidade no desenvolvimento de software envolve dividir uma aplicação em partes menores e mais independentes. Esses módulos servem a propósitos específicos e podem ser desenvolvidos e testados separadamente.
Cada pequeno conjunto de objetos funciona como uma unidade e lida com um aspecto do jogo. Isso pode ser qualquer coisa, desde controlar a entrada do jogador, lidar com a física ou contabilizar a pontuação.
Ao explorar os scripts do projeto, preste atenção nos seguintes pontos-chave:
- Construa suas cenas a partir de Prefabs: Você notará que a maioria das cenas no projeto são simplesmente coleções de Prefabs com mínimas substituições. Prefabs fornecem inerentemente um nível de modularidade. Resolver problemas de uma funcionalidade se torna uma questão de testar aquele Prefab específico em isolamento. Assim como ScriptableObjects, Prefabs são ativos em nível de projeto que podem ser reutilizados e compartilhados entre várias cenas.
- Use ScriptableObjects para armazenamento de dados (e mais): Evite usar MonoBehaviours para armazenar dados de jogabilidade estáticos. Em vez disso, aproveite ScriptableObjects para melhor reutilização. Você também pode delegar certa lógica de jogo a ScriptableObjects ou fazê-los facilitar a comunicação entre os objetos da sua cena.
- Separe as preocupações: Mantenha uma clara distinção entre dados, lógica e interface do usuário em seu projeto. Isso melhora a manutenibilidade do código e simplifica a depuração. Nosso sistema de tela de menu utiliza o mais novo UI Toolkit. Este sistema de UI impõe um fluxo de trabalho que separa a interface de sua lógica subjacente. Para mais detalhes, confira o e-book de design e implementação de interface do usuário em Unity.
- Minimize as dependências: Reduzir as dependências entre componentes facilita a modificação ou substituição de partes do seu projeto sem causar problemas imprevistos.
- Use eventos para comunicação: Eventos permitem um acoplamento solto entre componentes, permitindo que eles enviem mensagens uns aos outros sem dependências diretas. Você pode desacoplar ainda mais com "canais de eventos" baseados em ScriptableObject.
- Evite singletons desnecessários: Padrões de design singleton podem ser úteis, mas apenas quando uma única instância de uma classe é essencial. O uso excessivo de singletons pode resultar em código fortemente acoplado e dificultar os testes. Evite o singleton se não for necessário.
Refatorar um grande script monolítico em partes menores promove a reutilização e escalabilidade. Isso leva a uma melhor colaboração em equipe e testes simplificados.

ScriptableObjects em ação
Criamos o projeto PaddleBallSO para demonstrar casos de uso de ScriptableObject. Aqui estão alguns lugares específicos onde você os verá em ação:
- O ScriptableObject GameDataSO serve como um contêiner de dados central para as configurações do jogo. Edite seus dados comuns uma vez e, em seguida, compartilhe-os com os outros objetos que precisam deles.
- Os mini-jogos dependem de numerosos canais de eventos para se comunicar de maneira desacoplada. Esses eventos baseados em ScriptableObject formam a espinha dorsal de como os objetos enviam mensagens uns aos outros.
- A reprodução de som usa um objeto delegado baseado em ScriptableObject para separar a lógica do componente MonoBehaviour.
- Usamos um PlayerIDSO baseado em ScriptableObject enum para diferenciar "times" entre Player1 e Player2.
- O LevelLayoutSO ScriptableObject serve como um contêiner de dados para as posições iniciais de elementos do jogo, como as raquetes, gols, paredes e bola. Isso permite fácil modificação dos layouts de nível dentro do Unity e externamente via arquivos JSON exportados. A modificação dos designs de nível fora do Unity pode incentivar a criatividade dos jogadores e o compartilhamento de layouts personalizados.
Certifique-se de conferir as demonstrações de padrões de design para alguns extras também!

6 melhores práticas para ScriptableObjects
Embora os ScriptableObjects possam ser uma ferramenta poderosa para armazenar dados do jogo e agilizar seu fluxo de trabalho, é essencial usá-los de forma eficaz para evitar a desordem em seu projeto.
Aqui estão algumas melhores práticas para usar ScriptableObjects no Unity:
- Mantenha os dados modulares e organizados: Use ScriptableObjects separados para diferentes tipos de dados (por exemplo, um para estatísticas do jogador, um para comportamento de inimigos, etc.). Divida dados complexos em partes menores que podem ser facilmente gerenciadas.
- Use pastas e convenções de nomenclatura: ScriptableObjects podem ajudar a reduzir o código em seus scripts, mas a troca é lidar com mais ativos nas pastas do seu projeto. Uma nomenclatura adequada e organização de diretórios podem ajudar a gerenciar esses ScriptableObjects de forma eficiente. Confira nosso guia de estilo de código para dicas sobre nomenclagem.
- Evite o uso excessivo de ScriptableObjects: ScriptableObjects são contêineres de dados incríveis, mas é importante que você não os use em excesso. Tenha em mente que ScriptableObjects podem adicionar complexidade ao seu projeto, então use-os apenas quando oferecerem um benefício claro. (Por exemplo, não os use para salvar dados persistentes.)
- Faça backup dos dados regularmente: As alterações nos ScriptableObjects acontecem "ao vivo" em tempo de execução e são salvas como arquivos de ativos. Certifique-se de fazer backup do seu projeto regularmente para evitar a perda de dados. Use software de controle de versão para rastrear alterações em seus ScriptableObjects.
- Use a janela do Inspector: Uma vantagem chave dos ScriptableObjects é que eles são serializáveis e aparecem no Inspector. Aproveite a interface do Editor para visualizar e manipular dados armazenados em ScriptableObjects.
- Use scripts de Editor personalizados a seu favor: ScriptableObjects não podem referenciar objetos em tempo de execução da Hierarquia de Cena nativamente. Use a programação de Editor para tornar o Inspector uma interface mais amigável se você precisar visualizar esses objetos.
Seguindo estas diretrizes, você pode evitar armadilhas comuns no desenvolvimento.

Mais recursos de ScriptableObject
Leia mais sobre padrões de design com ScriptableObjects no e-book Crie uma arquitetura de jogo modular no Unity com ScriptableObjects. Você também pode descobrir mais sobre padrões de design comuns no desenvolvimento do Unity no e-book Melhore seu código com padrões de programação de jogos.