Se esta for a primeira vez que você lê conteúdos de nossa série, sinta-se especialmente convidado a conhecer mais sobre os projetos que estamos desenvolvendo, visando permitir que possamos, juntos, desbravar o interessante universo do desenvolvimento de jogos digitais.
Por meio do uso da ferramenta Unity, vamos explorar métodos, técnicas e ferramentas normalmente utilizados para a elaboração de aventuras digitais dos mais variados estilos gráficos e de gameplay. Os projetos que estamos elaborando desde o primeiro tópico da série buscam permitir a experimentação das diferentes formas possíveis para a elaboração e a configuração dos elementos pertencentes às fases e aos desafios de um game.
Abordamos desde as etapas mais elementares, como a instalação e a configuração da ferramenta Unity em nossos computadores, até os tópicos em que é necessário colocar a “mão na massa” pra valer, ao codificarmos scripts controladores de comportamentos e de regras de um game e ao configurarmos os aspectos relacionados aos elementos multimídia de fases e cenários do jogo.
Até o presente momento, já desenvolvemos dois jogos em nossa série, intitulados Motorista da Pesada e Forest Ping Pong. Trata-se de uma dupla de games 2D cujo desenvolvimento nos permitiu avançar nos conhecimentos em busca da criação de nosso primeiro jogo tridimensional, o puzzle Consultório do Dr. Tratanildo.
Todo o processo de desenvolvimento dos três games pode ser conferido a partir dos textos disponibilizados no índice, disponível no primeiro texto da série. Caso tenha gostado da ideia de aprender a tirar do papel suas próprias aventuras digitais, aproveite a oportunidade e junte-se a nós em uma divertida caminhada, repleta de novos conhecimentos e de muita diversão!
Um menu de verdade
A estrutura visual do menu de opções em nosso game ficou bem interessante, com ajustes visuais sendo realizados de forma semiautomática na tela, por intermédio da ação dos elementos Layout Group e Trigger Group sobre os elementos que introduzimos em encontros anteriores.
Embora a apresentação visual tenha sido bem implementada, de nada adiantarão as últimas intervenções em nosso projeto se as alterações de estado dos Triggers recém-introduzidos não refletirem em modificações no comportamento do jogo. Por isso, hoje iremos codificar scripts que realizarão a “ponte” entre as opções que o jogador vê e as mudanças comportamentais de nosso game.
Para tal, vamos abrir o projeto para edição. No Unity Hub, clique duas vezes sobre o item referente ao projeto Consultório do Dr. Tratanildo. Na interface inicial do Unity, na aba Project, abra a pasta Assets e, em seguida, Scenes. Clique duas vezes sobre o ícone da cena ConsultorioScene.
A primeira intervenção que realizaremos no projeto envolverá a adição de uma nova variável global ao script Geral. Na aba Project, abra a pasta Assets e, em seguida, Script. Clique duas vezes sobre o ícone do script Geral para iniciarmos sua edição no Visual Studio.
Imediatamente antes do fechamento de chaves da classe Geral, introduza as seguintes linhas de código:
// Modos de dificuldade: "Normal" e "Alta"
public static string Dificuldade = "Normal";
A nova variável introduzida, Dificuldade, registrará qual modo de dificuldade o jogador selecionou, por meio do menu de opções do game.
Por padrão, o valor inicial será equivalente ao de um nível de dificuldade mediano (“Normal”), podendo ser alterado para um valor que corresponda a um desafio mais elevado (“Alta”), caso o jogador deseje. A implementação das modificações comportamentais do jogo decorrente do nível de dificuldade selecionado será realizada em encontros posteriores.
Salve o script, minimize o Visual Studio e retorne ao Unity. Novamente na aba Project, ainda com a pasta Scripts em evidência, clique com o botão direito sobre um espaço vazio da pasta. No menu suspenso, selecione a opção Create e, em seguida, C# Script. Conceda o nome “ToggleVerificaStatus” ao novo script criado, clicando duas vezes sobre seu ícone após a nomeação para iniciarmos sua edição.
O novo script será responsável por permitir aos Toggles do menu de opções exibirem adequadamente as configurações de controles e de dificuldade armazenados nas variáveis globais de Geral.
Como o script realizará intervenções em aspectos da interface de usuário do jogo, adicione a seguinte linha ao final do conjunto inicial de declarações de bibliotecas do script (o bloco de comandos iniciados pela expressão using).
using UnityEngine.UI;
Em seguida, dentro das chaves que delimitam as funções e métodos do script ToggleVerificaStatus, remova as estruturas correspondentes à função Update, mantendo apenas as pertencentes à função void Start(). Dentro de suas chaves, introduza o grupo de linhas de código descrito a seguir.
switch (name)
{
case "OpcaoMouse":
GetComponent<Toggle>().isOn = Geral.ModoDeControle == "Teclado+Mouse";
break;
case "OpcaoTeclado":
GetComponent<Toggle>().isOn = Geral.ModoDeControle == "SoTeclado";
break;
case "OpcaoControle":
GetComponent<Toggle>().isOn = Geral.ModoDeControle == "Controle";
break;
case "OpcaoNormal":
GetComponent<Toggle>().isOn = Geral.Dificuldade == "Normal";
break;
case "OpcaoAlta":
GetComponent<Toggle>().isOn = Geral.Dificuldade == "Alta";
break;
}
Assim que o objeto a qual o script estiver atrelado for iniciado (Start), ToggleVerificaStatus verificará o nome do referido GameObject. Dependendo de qual for o objeto, seu componente Toggle terá sua caixa de seleção marcada (isOn = true) ou não (isOn = false) a partir do valor observado das variáveis ModoDeControle ou Dificuldade, presentes em Geral.
Na prática, o que pode ocorrer é o seguinte. Vamos supor que o objeto OpcaoMouse tenha um componente de tipo Toggle Verifica Status atrelado a si. Assim que ele for iniciado em cena, o componente Toggle atrelado a si terá a caixa de seleção marcada somente se a variável Geral.ModoDeControle tiver valor igual a “Teclado+Mouse”.
Para que esse comportamento ocorra de forma satisfatória a todos os Toggles, precisaremos atrelar cópias do componente Toggle Verifica Status aos respectivos GameObjects nomeados no script, o que iremos realizar daqui a pouco.
Controlador de opções
Salve o script, minimize o Visual Studio e retorne ao Unity. Novamente na aba Project, clique com o botão direito sobre um espaço vazio da pasta Scripts. No menu suspenso, selecione a opção Create e, em seguida, C# Script. Conceda o nome “AjusteOpcoes” ao novo script criado, clicando duas vezes sobre seu ícone após a nomeação para iniciarmos sua edição.
De modo semelhante ao que realizamos para o script ToggleVerificaStatus, será necessário inserirmos uma linha adicional ao final do conjunto inicial de declarações de bibliotecas do script (o bloco de comandos iniciados pela expressão using), dessa vez, relacionado ao uso de comandos derivados da biblioteca de eventos do Unity.
using UnityEngine.EventSystems;
Em seguida, dentro das chaves que delimitam as funções e métodos do script AjusteOpcoes, remova as estruturas correspondentes à função Update, assim como realizamos anteriormente para ToggleVerificaStatus, mantendo apenas as pertencentes à função void Start().
Dentro das chaves da função, introduza o seguinte grupo de linhas de código:
// Recuperação dos valores salvos em PlayerPrefs
if (PlayerPrefs.HasKey("ModoControle") == false)
PlayerPrefs.SetString("ModoControle", "Teclado+Mouse");
if (PlayerPrefs.HasKey("Dificuldade") == false)
PlayerPrefs.SetString("Dificuldade", "Normal");
Geral.ModoDeControle = PlayerPrefs.GetString("ModoControle");
Geral.Dificuldade = PlayerPrefs.GetString("Dificuldade");
Assim que o objeto a qual o script estiver atrelado for iniciado (Start), as variáveis correspondentes ao modo de controle e ao nível de dificuldade presentes em Geral terão seus valores substituídos pelos armazenados em PlayerPrefs, permitindo que haja o armazenamento das preferências entre sessões de jogo. Caso as chaves armazenadoras de valores em PlayerPrefs não tenham sido criadas, receberão os valores padrão (“Teclado+Mouse”, para “ModoControle”, e “Normal”, para “Dificuldade”).
Em seguida, imediatamente antes do último fechamento de chaves de AjusteOpcoes, introduza o seguinte grupo de linhas de código no script:
public void AtualizarValores(bool toggleOn)
{
if (toggleOn)
{
GameObject toggleClicado = EventSystem.current.currentSelectedGameObject;
switch (toggleClicado.name)
{
case "OpcaoMouse":
Geral.ModoDeControle = "Teclado+Mouse";
break;
case "OpcaoTeclado":
Geral.ModoDeControle = "SoTeclado";
break;
case "OpcaoControle":
Geral.ModoDeControle = "Controle";
break;
case "OpcaoNormal":
Geral.Dificuldade = "Normal";
break;
case "OpcaoAlta":
Geral.Dificuldade = "Alta";
break;
}
PlayerPrefs.SetString("ModoControle", Geral.ModoDeControle);
PlayerPrefs.SetString("Dificuldade", Geral.Dificuldade);
}
}
AtualizarValores é uma função que recebe como parâmetro um valor booleano por meio da variável toggleOn. Caso o valor informado de toggleOn for positivo (true), a função realizará a seguinte sequência de ações:
- Verificará, por intermédio do sistema de eventos do Unity (EventSystem), qual foi o último GameObject selecionado em cena (por meio de um clique, por exemplo), armazenando uma referência ao objeto na variável toggleClicado;
- Dependendo do nome “real” do objeto toggleClicado, as variáveis ModoDeControle e Dificuldade, pertencentes ao script Geral, poderão ter seus valores modificados;
- Por fim, os valores atuais presentes nas variáveis de controle e de dificuldade de Geral são armazenados em chaves de PlayerPrefs, garantindo que estejam disponíveis, mesmo após o término da sessão de jogo.
Embora a sequência de ações proposta faça sentido e aparenta ser simples, você pode estar se perguntando no momento o por quê de termos condicionado a execução dos códigos a um valor específico para a variável toggleOn. Fique tranquilo, pois trata-se de uma estratégia para que apenas determinados Toggles possam modificar os valores das preferências do jogador por vez. Entenderemos melhor esta estratégia durante as intervenções que realizaremos daqui a pouco.
Salve o script, feche o Visual Studio e retorne ao editor do Unity para prosseguirmos com nossas intervenções de hoje.
O pulo do gato
De volta ao editor do Unity, na aba Hierarchy, crie um novo GameObject vazio, não subordinado aos demais objetos. Seu nome será “ControladorOpcoes” e os valores de Position e de Rotation de seu componente Transform devem ser iguais a zero, conforme ilustração a seguir.
Ainda com ControladorOpcoes em evidência, na aba Inspector atrele ao GameObject um componente de tipo Ajuste Opcoes. A partir de agora, ControladorOpcoes será o objeto de referência para controle das opções do menu em nosso game.
A seguir, na aba Hierarchy, selecionaremos todos os objetos que contenham componentes de tipo Toggle atrelados a si. Para tal, na caixa de pesquisa, digite a palavra “toggle” (sem as aspas) para que os objetos com este tipo de componente sejam listados. Selecione os cinco GameObjects para editarmos suas propriedades simultaneamente.
Na aba Inspector, localize as propriedades de seus componentes de tipo Toggle. Ao final da lista, será exibido um conjunto de itens de nome On Value Changed (Boolean). Sua configuração é semelhante ao das opções configuráveis de On Click (), presente em componentes do tipo Button, com uma diferença essencial: o valor atual de Is On pode ser informado a uma função que seja indicada a ser executada, ao se clicar no Toggle.
Clique sobre o ícone com o sinal de mais; em seguida, no campo indicado em azul, conceda o valor correspondente ao objeto ControladorOpcoes; logo após, clicando no botão destacado em laranja, selecione no menu suspenso a opção AjusteOpcoes e, em seguida, a opção AtualizarValores da primeira seção do menu (Dynamic bool).
Ao indicarmos ao Unity que a função AtualizarValores de AjusteOpcoes deverá ser chamada assim que o valor do atributo Is On de um dos componentes Toggle for modificado, será a variável toggleOn da função AjusteOpcoes que receberá o valor do atributo Is On no ato de sua execução.
É neste ponto que mora o “pulo do gato” da função que criamos há pouco: apenas Toggles que estejam com suas caixas de seleção marcadas (isOn = true) poderão fazer com que a função AtualizarValores seja devidamente executada, modificando o valor das variáveis de dificuldade e de controles do jogo somente para aqueles correspondentes aos elementos selecionados no menu de opções pelo jogador.
Ainda com os cinco objetos selecionados, via aba Inspector, adicione aos GameObjects componentes do tipo Toggle Verifica Status. Essa adição garantirá que, desde o início da sessão de jogo corrente, os Toggles mostrem os valores corretos das configurações escolhidas pelo jogador.
Por fim, limpe a caixa de pesquisa da aba Hierarchy e, em seguida, vá até a aba Game e clique sobre o ícone do botão Play para iniciar a simulação da execução do jogo. Experimente realizar trocas nos modos de controle do jogo; verifique também se as escolhas realizadas pelo jogador persistem entre sessões de jogo, desligando e ligando a simulação da execução.
Interrompa a simulação de execução, clicando novamente sobre o ícone do botão Play e retornando à aba Scene. Não se esqueça de salvar a cena (menu File, Save) e o projeto (menu File, Save Project) antes de fechar o Unity.
Próximos passos
Ao realizarmos a codificação do comportamento dos elementos do menu de opções, chegamos mais perto da finalização da construção de nosso game, ao darmos ao jogador o poder de escolher como ele quer interagir e qual a dificuldade que deseja para os desafios propostos.
Nos próximos encontros, realizaremos a codificação de controles do jogo utilizando um controle de videogame como referência, além de modificações que serão necessárias para darmos vida ao “modo hard” de nosso game.
Nos encontraremos novamente no próximo dia 19 de julho. Até mais! Fique ligado sempre nas novidades do GameBlast!
Revisão: Ives Boitano




















