0% acharam este documento útil (0 voto)
96 visualizações49 páginas

Unity 3D

1) A Unity 3D é um software que facilita o desenvolvimento de jogos permitindo criar jogos para diversas plataformas sem precisar programar diretamente para APIs gráficas. 2) Além de ser multiplataforma, a Unity possui uma interface amigável e ferramentas visuais que tornam o desenvolvimento de jogos mais fácil em comparação a outros motores. 3) A Unity suporta a importação de vários formatos de arte 2D e 3D de softwares populares e permite criar shaders com diferentes linguagens.

Enviado por

Manuel Panda
Direitos autorais
© © All Rights Reserved
Levamos muito a sério os direitos de conteúdo. Se você suspeita que este conteúdo é seu, reivindique-o aqui.
Formatos disponíveis
Baixe no formato DOCX, PDF, TXT ou leia on-line no Scribd
0% acharam este documento útil (0 voto)
96 visualizações49 páginas

Unity 3D

1) A Unity 3D é um software que facilita o desenvolvimento de jogos permitindo criar jogos para diversas plataformas sem precisar programar diretamente para APIs gráficas. 2) Além de ser multiplataforma, a Unity possui uma interface amigável e ferramentas visuais que tornam o desenvolvimento de jogos mais fácil em comparação a outros motores. 3) A Unity suporta a importação de vários formatos de arte 2D e 3D de softwares populares e permite criar shaders com diferentes linguagens.

Enviado por

Manuel Panda
Direitos autorais
© © All Rights Reserved
Levamos muito a sério os direitos de conteúdo. Se você suspeita que este conteúdo é seu, reivindique-o aqui.
Formatos disponíveis
Baixe no formato DOCX, PDF, TXT ou leia on-line no Scribd
Você está na página 1/ 49

A Unity 3D é um software que possibilita o desenvolvimento de jogos.

Assim como toda game engine, ela facilita o desenvolvimento de jogos pelo
fato de o desenvolvedor não precisar programar diretamente para DirectX ou
OpenGL, pois ela já faz isso automaticamente. A Unity pode fazer jogos para
produtos da Apple (Mac, iPhone, iPod, iPad), da Microsoft (Xbox, Windows),
da Google (dispositivos com Android), da Sony (Playstation 3), da Nintendo
(Wii) e para navegadores Web (Internet Explorer, Mozilla Firefox, Google
Chrome, Opera e Safari).

Além dessa portabilidade, a Unity possui uma grande quantidade de


ferramentas e é muito fácil de trabalhar com ela, pois além de ser visual (não
apenas baseada em código como a Irrlicht, por exemplo) a interface é bastante
amigável. Ela possui uma ferramenta de scripts baseada no Mono (ferramenta
para desenvolver e executar aplicações .NET em diferentes plataformas),
possibilitando a programação em C#, UnityScript e Bool.

A Unity também permite a criação de Shaders com a linguagem SharderLab,


Cg da NVidia, GLSL para o OpenGL e trabalha também com Shader Mode. O
subsistema de simulação física é o PhysX, também da NVidia. Ela usa
também bibliotecas Direct X, Open GL para renderização 3D e OpenAL para
áudio.

Outro ponto forte da Unity é a importação de arquivos. Ela importa em


vários formatos, tanto 2D quanto 3D, o que exclui o trabalho de ter que
exportar alguma arte antes de importar na Unity. Ela aceita os arquivos dos
seguintes programas:

 Blender: .blend;
 Autodesk 3DS Max: .max;
 Autodesk Maya: .mb or .ma;
 Maxon CINEMA 4D: .c4d;
 Cheetah3D: .jas;
 Luxology Modo 3D: .lxo - a partir do modo 501;
 NewTek LightWave: é necessário exportar para .fbx utilizando o plugin
para exportar para fbx do LightWave.

Unity também lê arquivos .FBX, .dae, .3DS, .dxf, .obj e também aceita o
.collada. Para arquivos de textura (arquivos 2D) ela aceita os formatos: PSD,
TIFF, JPG, TGA, PNG, GIF, BMP, IFF, PICT.

O motor gráfico da Unity 3D usa Direct3D (Windows, Xbox 360), OpenGL


(Mac, Windows, Linux, PS3), OpenGL ES (Android, iOS) e APIs
proprietárias (Wii). Há suporte para mapeamento de relevo, mapeamento de
reflexão, mapeamento de parallax, ambient occlusion (SSAO), sombras
dinâmicas usando mapas de sombra, render-to-texture e efeitos de pós-
processamento.

A Unity suporta conteúdo de arte e formatos de arquivos de 3ds Max, Maya,


Softimage, Blender, modo, ZBrush, Cinema 4D, Cheetah3D, Adobe
Photoshop, Adobe Fireworks e substância Allegorithmic. Esses assets podem
ser adicionados ao projeto de jogo, e utilizados através da interface gráfica da
Unity.

A linguagem ShaderLab é usada para shaders, escritos em GLSL e Cg. Um


shader pode incluir múltiplas variantes e uma especificação fallback
declarativa, permitindo que a Unity detecte a melhor variante para a placa de
vídeo atual.

A partir da Unity 4.2, foi adicionado à versão free sombras em tempo real para
luzes direcionais e também foi adicionado suporte ao DirectX11, o que dá às
sombras uma resolução perfeita dos pixels, texturas para criar objetos 3D a
partir de tons de cinza, gráficos, animações faciais mais suaves e um impulso
para o frames per second.

A engine também conta com a Unity Asset Server - uma solução de controle
de versão para os assets e scripts. Ele usa PostgreSQL como um backend, um
sistema de áudio construído sobre a biblioteca FMOD (com capacidade de
reprodução de áudio Ogg Vorbis comprimido), reprodução de vídeo usando o
Theora codec, um motor de terreno e vegetação (que suporta Tree
Billboarding, Occlusion Culling com Umbra), lightmapping embutido e
iluminação global com Beast, rede multijogador usando RakNet, e pathfinding
mesh navigation embutido.

Além disso, ela também foi construída com suporte para a engine de física
Nvidia PhysX (a partir da Unity 3.0) com suporte adicional para a simulação
de tecido em tempo real, raycasts e camadas de colisão.

A Unity3D além dessas características é free, apesar de ter a versão Pro que
tem um preço não fora da realidade.

Primeiros passos

O exemplo criado para este artigo utilizou a versão 4.2 da Unity 3D, a qual
pode ser encontrada no endereço que consta na seção Links. Após instalação,
o primeiro passo será criar um projeto para criarmos nosso jogo eletrônico.
Para isto, basta clicar sobre o ícone da Unity que veremos o wizard para
criação de projetos, conforme Figura 1. Caso a Unity já abra o projeto
demostranstrativo - o qual já vem instalado juntamente com o software,
selecione no menu superior File -> New Project.

Figura 1. Project Wizard

Em seguida, na aba Create New Project, vamos definir uma pasta no sistema
para receber todos os arquivos que farão parte do projeto. Seguindo o exemplo
deste artigo, iremos criar uma pasta nomeada Point and Click diretamente no
desktop.

Perceba que abaixo do campo em que definimos a pasta do nosso projeto


temos um conjunto de pacotes com a extensão .unityPackage que podem ser
importados. Estes pacotes contêm uma variedade de elementos previamente
prontos para construção de um novo jogo, ou seja, diversos objetos que
poderão ser utilizados. Como estamos tratando neste artigo dos primeiros
passos e contato com esta engine de jogos, não iremos utilizar nenhum deles.

Conceito

Especificamente no ramo de desenvolvimento de jogos temos um momento


que chamamos de concept, onde geramos a ideia para o jogo e definimos qual
será a mecânica principal do mesmo. No caso do exemplo criado para este
artigo, será um point and click, ou seja, a interação do jogador com jogo se
dará através do ponteiro do mouse sobre os elementos contidos nas telas do
próprio jogo.

Em seguida, com a ideia definida, elaboramos como serão as regras do jogo,


descrevendo suas características, juntamente com as condições de vitória e
derrota, entre outros - o que podemos chamar de game design, ou seja, as
especificações do projeto de jogo.

Primeiramente, vamos definir o High Concept como um jogo de click de


mouse em alta velocidade, com o objetivo principal de destruir a maior
quantidade possível de objetos no cenário, para acumular pontos e definir uma
pontuação final elevada. O controle do jogo será apenas o botão esquerdo do
mouse, com o qual apontaremos e destruiremos os objetos em tela. E, por fim,
utilizaremos objetos 3D como alvos e efeitos de partículas para destacar a
destruição de cada um dos objetos alvos.

A elaboração deste jogo tem a finalidade de abordar os seguintes temas


dentro da Unity 3D:

 Introdução à criação de assets;


 Introdução à criação de scripts;
 Introdução à criação de elementos de interface - GUI (Graphic User
Inteface);
 Introdução às entradas de comando de jogo utilizando o mouse - Inputs;
 Introdução a eventos;
 Introdução ao carregamento de telas - Scenes.

Interface

O motor de jogos Unity 3D possui uma interface bastante simples e amigável


que objetiva facilitar o desenvolvimento de jogos de diversos gêneros e outros
sistemas de visualização. Sua área de trabalho é composta de várias janelas
chamadas views, cada uma com um propósito específico. A Figura 2 é uma
captura contendo a representação esquemática inicial das janelas no editor da
Unity3D.
Figura 2. Interface inicial

Scene View

A Scene View é sua “caixa de areia” interativa. Ela é utilizada para selecionar
e posicionar os ambientes, o jogador, as câmeras, inimigos, e todos os outros
GameObjects. Manobra e manipulação de objetos dentro da Scene View são
algumas das funções mais importantes da Unity, então é importante estar apto
a fazê-los rapidamente.

Navegação da Scene View

Para facilitar o uso da Unity 3D, vamos entender alguns fundamentos de


navegação na Scene View:

 Segurando o botão direito do mouse, entra-se no modo flythrough


(aéreo), permitindo girar o cenário.
 Ao selecionar qualquer GameObject e pressionar a tecla F, centralizará
o ponto pivô (encontro dos eixos x, y, z) no centro do objeto na Scene
View.
 Segurando Alt e clicando com o botão esquerdo do mouse é possível
girar a câmera em torno do pivô do objeto corrente.
 Segurando Alt e clicando com o botão do meio do mouse é possível
arrastar um GameObject pela Scene View.
 Segurando Alt e clicando com o botão direito do mouse é possível dar
zoom na Scene View. A mesma ação pode ser feito utilizando o scroll
do mouse.

No canto superior direito da Scene View há o Scene Gizmo. Este mostra a


atual orientação da câmera da Scene, e permite modificar rapidamente o
ângulo de visão, conforme Figura 3.

Figura 3. Interface inicial

ToolBar (Barra de Ferramentas)

Disposto na parte superior da interface há um conjunto de ferramentas que nos


permite operar e manipular a interface, o jogo e seus elementos,
conforme Figura 4.

Figura 4. Toolbar

A barra de ferramentas consiste em cinco controles básicos. Cada um se refere


a diferentes partes do editor.

1. Ferramentas de Transformação: usadas com a Scene View.

2. Alternador de Gizmo de Transformação: afeta a tela no Scene View.

3. Botões Play/Pause/Step: utilizados com a Game View (Visão do jogo).

4. Caixa suspensa de camadas: controla quais objetos são mostrados na Scene


View.

5. Caixa suspensa de Layout: Controles dispostos em todas as Views.


Se apertarmos no botão Play, poderemos ver a troca entre a Scene View e a
Game View, onde surgirá uma tela azul, significando o atual estado do nosso
jogo, conforme Figura 5.

Figura 5. Game View

É habitual no desenvolvimento de jogos verificarmos constantemente como


está ficando a visualização do jogo, logo, podemos alterar a interface de
trabalho para permitir a visualização das abas Scene e Game simultaneamente.

No canto superior direito da interface, conforme Figura 6, temos um conjunto


de opções na janela suspensa Layout, com a finalidade de oferecer outras
formas de visualização. Além das opções disponíveis, é possível customizar a
interface livremente selecionando qualquer uma das views, arrastando-as e
soltando-as sobre a qualquer outra localidade.

Figura 6. Layout
No sentido de oferecer uma visualização mais fácil para o desenvolvedor,
podemos arranjar a interface conforme Figura 6 e por fim salvá-la na opção
Save Layout, também incluso na Figura 7. Este novo arranjo das
views permitirá visualizarmos as abas Scenes e Game simultaneamente,
conforme mencionado anteriormente.

Figura 7. Interface criada

Durante o desenvolvimento do jogo, iremos, conforme a necessidade,


conhecer o que são e para que serve cada uma das abas dispostas na interface
e também os elementos que podem ser utilizados para a criação de jogos.
Começaremos pela aba Project View.

Project View (Visão do Projeto)

Todo projeto Unity contém uma pasta de Assets (ativos - BOX 1). O


conteúdo dessa pasta é apresentado no Project View, conforme a Figura 8.
Este é local onde são armazenados todos os assets que irão compor o jogo,
como cenas, scripts, modelos 3D, texturas, arquivos de áudio e prefabs (pré-
fabricados). Se clicarmos com o botão direito em qualquer asset no Project
View, é possível selecionar a opção Show In Explorer para realmente ver o
asset no sistema de arquivos do computador.
Figura 8. Project View

Assets

A palavra "assets" faz referência a todos os ativos para a criação de um jogo


eletrônico, ou seja, qualquer item como modelos 3D, texturas, scripts,
arquivos de áudio, entre outros.

É recomendado nunca mover os assets do projeto através das pastas do


sistema operacional, uma vez que existe a possibilidade de corromper todos os
metadados associados ao asset. Logo, sempre se usa o Project View para
organizar os assets.

Para adicionar assets ao projeto, podemos arrastar qualquer arquivo do


sistema operacional para dentro do Project View, ou usar a opção Assets -
> Import New Asset no menu superior da Unity. Desta forma, o asset estará
pronto para ser utilizado no jogo.
Scripts

Agora que já conhecemos a aba Project View, podemos criar um script para o
projeto. Conforme já comentando, os scripts dentro da Unity podem ser
desenvolvidos em UnityScript, C#, ou Boo. É possível utilizar uma ou todas
as linguagens de script em um único projeto, pois não há nenhuma penalidade
por usar mais de uma.

Criando novos Scripts

Ao contrário de outros assets, como meshs (malhas) ou textures (texturas),


arquivos de script podem ser criados a partir de dentro da própria Unity. Para
criar um novo script, temos duas opções. A primeira seria clicar no botão
Create, posicionado no alto da aba Project, como pode ser visto na Figura 8, e
selecionar em seguida C# Script (já que utilizaremos C# como linguagem de
programação neste artigo). A segunda opção pode ser encontrada no menu
superior da interface, na opção Assets -> Create -> C# Script,
conforme Figura 9.

Figura 9. Create C# Script


Esta ação irá criar um novo script chamado NewBehaviourScript e colocá-lo na
pasta selecionada no Project View. Se nenhuma pasta estiver selecionada no
Project View, o script será criado na pasta raiz Assets.

Para editar o script criado, basta clicar duas vezes sobre ele no Project View.
Isso iniciará o editor selecionado nas preferências da Unity, que por padrão
será o MonoDeveloper. Logo, todos os scripts serão alterados em um editor de
texto externo, e não diretamente na Unity. Se preferir o Visual Studio, basta
alterar a opção em Edit -> Preferences -> External Tools -> External Script
Editor.

Prosseguindo com o projeto, vamos alterar o primeiro script criado com o


nome de NewBehaviourScript para ScriptPlayer. Um ponto importante aqui é que
ao alterar o nome do arquivo com extensão .cs, é preciso também alterar o
nome da classe dentro do arquivo. Os dois devem ter obrigatoriamente o
mesmo nome para o Mono compilá-lo corretamente.

Em seguida, vamos criar os seguintes scripts para o projeto, além do já criado


ScriptPlayer:

 ScriptEnemy;
 ScriptScreenMainMenu;
 ScriptScreenWin;
 ScriptScreenLose.

O resultado pode ser visto na Figura 10.


Figura 10. Scripts

GameObjects

Agora vamos inserir no projeto alguns objetos para podermos manipulá-los


via script. Estes objetos são os GameObjects e são eles os elementos mais
importantes na Unity. É muito importante entender o que é um GameObject e
como ele pode ser usado.

Cada objeto no jogo é um GameObject. No entanto, GameObjects não fazem


nada sozinhos. Eles precisam de propriedades especiais antes que eles possam
se tornar um personagem, um ambiente, ou um efeito especial. Mas cada um
desses objetos pode fazer muitas coisas diferentes, pois GameObjects são na
verdade recipientes. Eles são caixas vazias que podem conter diferentes peças
que podem compor uma ilha com lightmap (mapa de luz) ou um carro com
direção física. Assim, para realmente compreender GameObjects, é preciso
entender outro elemento da Unity chamado Component (Componente).
Dependendo do tipo de objeto que será criado, serão adicionadas diferentes
combinações de Components para o GameObject.

Podemos imaginar que um GameObject é uma panela vazia e componentes


são como diferentes ingredientes que comporão a receita de jogabilidade.
Assim, é possível criar nossos próprios Components utilizando Scripts.

A Unity nos oferece alguns GameObjects em forma de primitivas gráficas


para prototiparmos ou até mesmo utilizarmos no jogo. Para entendermos onde
inseri-los, precisaremos entender a view Hierarchy, conforme Figura 11.

Figura 11. Hierarchy View (Visão da Hierarquia)

A aba Hierarchy conterá todos os GameObject (Objeto de jogo) na Scene


corrente. Alguns desses são instâncias diretas de arquivos de assets, como
modelos 3D, e outros são instâncias de prefabs - objetos customizados que
irão compor o jogo. Podemos selecionar e paternizar objetos na Hierarchy.
Como objetos são adicionados e removidos da Scene, eles irão aparecer e
desaparecer da Hierachy também.

Inicialmente iremos criar dois objetos, uma Sphere (esfera) e um Cube (cubo).
Para incluir estes elementos na Hierarchy temos duas possibilidades. A
primeira seria clicar no botão Create, posicionado no alto da aba Hierarchy,
como pode ser visto na Figura 11, e selecionar em seguida Sphere e Cube. A
segunda opção pode ser encontrada no menu superior da interface, na opção
GameObject -> Create Other -> Sphere e/ou Cube, conforme Figura 12.
Figura 12. GameObjects

Agora, para melhor entendimento das funções destes objetos, vamos renomeá-
los para EnemyCircle(Sphere) e EnemySquare (Cube). Logo em seguida,
precisaremos criar “n” instâncias dos dois tipos de inimigos criados,
associando a eles futuramente um script para manipulá-los. Para evitar o
retrabalho de associar o script para cada GameObject, iremos criar Prefabs.

Criando um Prefab

Prefabs são uma coleção de GameObjects e Components que podem ser


reutilizados nas Scenes do jogo. Muitos objetos idênticos podem ser criados a
partir de um único Prefab, ou seja, instanciados. Se usarmos como exemplo
um modelo 3D de uma árvore e criarmos um Prefab para o mesmo, estaremos
permitindo a instanciação de muitas árvores idênticas e colocando-as em
diversas Scene diferentes. Isso acontecerá por que o modelo 3D da árvore
estará ligado ao Prefab, permitindo que qualquer mudança que for feita
diretamente no Prefab seja aplicada automaticamente em todas as instâncias
de árvores. Então, se for necessário alterar o mesh (malha), o material, ou
qualquer outra coisa, basta realizar a mudança no Prefab e todas as outras
árvores herdarão a mudança.

Para realmente criarmos um Prefab a partir de um GameObject da Scene,


primeiro criaremos um novo Prefab no Project View. Desta vez temos três
possibilidades. A primeira seria clicar no botão Create, posicionado no alto da
aba Project, como pode ser visto na Figura 8, e selecionar em seguida Prefab.
A segunda opção pode ser encontrada no menu superior da interface, na opção
Assets -> Create -> Prefab, conforme Figura 13.

Figura 13. Criando Prefabs

Para o projeto, nomearemos os Prefabs com os mesmo nomes dos


dois GameObject adicionados à Scene anteriormente, inserindo a palavra Prefab
no início das palavras. Em seguida, podemos arrastar cada um
dos GameObjects para seu Prefab relacionado e veremos o texto do nome mudar
para azul. A terceira e última opção foi adicionada recentemente nas últimas
versões, a qual pode ser feita apenas arrastando os GameObjects da aba
Hierarchy para a aba Project. Com isso, temos agora Prefabs reutilizáveis,
conforme Figura 14.
Figura 14. Novos Prefabs

Depois de criados os Prefabs, podemos excluir os GameObjects EnemyCircle


e EnemySquare da aba Hierarchy e consequentemente da Scene, já que
faremos a inclusão de inimigos no jogo dinamicamente via script e utilizando
como modelo os Prefabs recentemente criados.

A título de conhecermos softwares de criação de jogos 3D, iremos conhecer


agora o termo Material, ou seja, um componente que será anexado a um
GameObject, visando oferecer alguma forma de identificação visual, através
de cores, texturas e iluminação diferenciada sobre o próprio objeto.
Resumindo, assemelhando-se de materiais que podemos encontrar no mundo
real.

Vamos criar dois Materials (MatEnemyCircle e MatEnemySquare) para


associarmos aos dois Prefabs. Novamente, temos duas opções. A primeira
seria clicar no botão Create, posicionado no alto da aba Project (Figura 8) e
selecionando em seguida Material. A segunda opção pode ser encontrada no
menu superior da interface, na opção Assets -> Create -> Material. Na Figura
15 vemos os materiais que foram criados.
Figura 15. Materials

Para associarmos Materials aos Prefabs, basta arrastar cada um dos materiais
sobre o Prefab correspondente. Em seguida, podemos também arrastar o
mesmo script ScriptEnemy sobre os dois Prefabs. Desta forma teremos os
GameObjects em forma de círculo e cubo associados a respectivos materiais e
a um script através de um Prefab. O resultado pode ser visto na aba
Inspector ao selecionarmos qualquer um dos Prefabs, conforme a Figura 16.
Figura 16. Inspector

Inspector(Inspetor)

Os jogos feitos na Unity são feitos de múltiplos GameObjects que contêm


meshes, scripts, sounds, ou outro elemento gráfico como ligths. O Inspector
tem a finalidade de mostrar informações detalhadas sobre o GameObject
selecionado no momento, incluindo todos os Components anexados a ele e
suas propriedades.

Qualquer propriedade que é mostrada no Inspector pode ser diretamente


modificada. Mesmo variáveis de scripts podem ser modificadas sem alteração
do próprio script. Pode-se usar o Inspector para mudar variáveis em tempo de
execução para experimentar e encontrar a jogabilidade perfeita de um jogo.
Em um script, se for definida uma variável pública de um tipo de objeto
(como GameObject ou Transform), é possível arrastar e soltar um
GameObject ou Prefab dentro do Inspector para fazer a associação. Veremos
como fazer isso no decorrer deste artigo.

Agora que temos todos os assets necessários para a construção do jogo, vamos
salvar o que temos até aqui dentro de uma Scene.

Scenes

As Scenes, ou seja, as telas do jogo, também são armazenadas no Project


View. Pode-se imaginá-las como níveis individuais de um jogo completo.
Para salvar a Scene atual podemos clicar no menu superior em File -> Save
Scene ou simplesmente através do atalho Ctrl + S e nomeá-la como
SceneGameLevel. Qualquer Scene criada para o jogo ficará salva também
dentro da pasta Assets, vista na aba Project, conforme Figura 17.
Figura 17. Scene salva

De volta ao projeto, é preciso agora posicionar o objeto Main Camera, na


Hierarchy, com as seguintes configurações:

 Primeiramente devemos clicar sobre o objeto para surgirem seus


componente na aba Inspector;
 Definir os valores do componente Tranform, configurando Position (x:
0, y: 0, z: -10), Rotation (x: 0, y: 0, z: 0) e Size (x: 1, y: 1, z: 1);
 Abaixo do componente Transform há o componente Camera, o qual é
responsável pelo tipo de visão do jogo. Para este artigo utilizaremos a
propriedade Projection como Orthographic, Size com valor 5, Clipping
Planes com Near 0.3 e Far 20. Sem entrar em muitos detalhes, estas
mudanças permitirão trabalhar o jogo com uma visualização 2D em um
ambiente 3D.

Lembrar sempre de salvar a cena após alguma alteração nos objetos contidos
na mesma (os mesmos listados na aba Hierarchy). O resultado final das
alterações na câmera pode ser visto na Figura 18.
Camera Inspectorb>Figura 18. Camera Inspector

Com a câmera configurada, pode-se testar como ficarão os Prefab na tela de


jogo (aba Game). Para isso, vamos alterar a opção da combo no canto superior
direito da aba Game de Free Aspect para Standalone (1024x768) - definindo
as proporções da tela de jogo - e em seguida arrastaremos um dos
Prefabs para a aba Hierarchy ou na aba Scene e o posicionaremos nas
coordenadas x: 0, y: 0 e z: 0 na propriedade Position que está dentro do
componente Transform. Ao final desta ação se pode visualizar o objeto de
frente para a câmera, conforme Figura 19, mas percebe-se que o cenário está
escuro. Para resolver esse problema devemos adicionar ao cenário um
componente de luz, que no caso será um Directional Light. Podemos adicioná-
lo da mesma forma que adicionamos a Sphere e o Cube anteriormente:
clicando no botão Create da aba Hierarchy ou no menu superior em
GameObject -> Create Other -> Directional Light e em seguida ajustá-lo com
todos os eixos de Position e Rotation com valor 0. O resultado pode ser visto
na Figura 20.

Figura 19. Game View (sem iluminação)

Figura 20. Directional Light

Agora, vamos inserir alguma ação no jogo. Para isso, vamos abrir o arquivo
ScriptPlayer clicando duas vezes sobre ele. Para este artigo, o IDE de
programação escolhida foi o próprio MonoDeveloper.

Ao abrirmos o script veremos a estrutura da Listagem 1, onde existirão


apenas os métodos Start e Update, os quais serão consumidos
automaticamente pelo motor de jogos, ou seja, a preocupação do
desenvolvedor será apenas com a lógica de gameplay, não precisando se
preocupar com gerenciamento de tempo, memória e renderização gráfica.

Listagem 1. Script C#.


01 using UnityEngine;
02 using System.Collections;
03
04 public class ScriptPlayer : MonoBehaviour
05 {
06 // Use this for initialization
07 void Start()
08 {
09
10 }
11
12 // Update is called once per frame
13 void Update()
14 {
15
16 }
17 }

Através dos comentários sobre os métodos podemos entender que o método


Start será chamado somente uma vez - na inicialização da Scene - e o método
Update será chamado a cada frame (de acordo com o clock/ciclo de máquina).
Então, será através do código script dentro deste método que teremos os
objetos do jogo se movimentando e alterando seus comportamentos. Se
desejar conhecer todos os recursos deste framework, as referências
bibliográficas foram instaladas juntamente com o software. Para acessar,
pode-se clicar no menu superior em Help -> Scripting Reference que abrirá no
navegador padrão o caminho onde está a documentação.

O PlayerScript conterá a lógica de click do mouse e para isso precisaremos


implementar a lógica que recupera o click com o botão esquerdo deste device,
conforme a Listagem 2. O script (ou mesmo class) que contém todas as
detecções de entradas de teclado, mouse, touch e outros se chama Input. Nele
podemos encontrar diversos métodos direcionados para cada tipo diferente de
dispositivo de entrada e até mesmo o conjunto de teclas a partir do enum
KeyCode.

Listagem 2. Mouse Button Down.


01 using UnityEngine;
02 using System.Collections;
03
04 public class ScriptPlayer : MonoBehaviour
05 {
06 // Use this for initialization
07 void Start()
08 {
09
10 }
11
12 // Update is called once per frame
13 void Update()
14 {
15 // Verificando se foi clicado com o botao esquerdo do mouse.
16 if (Input.GetMouseButtonDown(0))
17 {
18 Debug.Log("O clique funcionou!");
19 }
20 }
21 }

No código da Listagem 2 foi utilizado o método GetMouseButtonDown, pois


ele é o correto quando quisermos detectar o ponto final do click do mouse, ou
seja, quando ele foi completamente "abaixado". Há outros dois métodos
semelhantes: GetMouseButtonUp e GetMouseButton, onde o primeiro detecta
quando a tecla do mouse foi totalmente recuada à sua posição original e o
segundo detecta se a tecla do mouse está sendo pressionada.

Quanto ao parâmetro 0 (zero) passado no método, ele significa a primeira


posição no array de possibilidades do mouse, onde 0 é o botão esquerdo, 1 o
botão direito e 2 o botão central.

Se a condição do if for atendida, vamos escrever na aba Console a mensagem


"O clique funcionou!". A Console View pode ser vista no canto inferior-
direito da Unity na Figura 20. Caso não, pode-se abri-la clicando no menu
superior em Windows -> Console ou através do atalho Ctrl + Shift + C. Esta
aba é extremamente útil para depuração de código, pois a atualização de
aproximadamente 60 vezes por segundo do código inserido no método Update
dificulta o melhor uso de breakpoints.
Retornando para a interface da Unity, arrastaremos o script recém-alterado
(ScriptPlayer) para sobre o GameObject Main Camera, pois ele funcionará
para este exemplo como o jogador. O resultado pode ser visto na parte inferior
da Figura 21 com o script fazendo parte dos componentes do objeto da
Câmera.

Figura 21. Aplicando um Script ao GameObject

Agora é o momento de testar. Vamos clicar no botão Play no topo da interface


e clicar quantas vezes forem necessárias, com isso, visualizando a mensagem
sendo escrita na aba Console na mesma quantidade. Desmarque o botão
Collapse para ter o mesmo resultado da Figura 22.

Figura 22. Escrevendo na aba Console

Independente onde for feito o click dentro da tela de jogo, a mensagem será
escrita igualmente. O próximo passo é identificar o click somente sobre algum
dos Prefabs.

Após testar, é importante não se esquecer de clicar no mesmo botão Play para
dar Stop, pois qualquer alteração feita na Scene enquanto o jogo estiver em
execução será perdida após o Stop, pois alteração em jogo, obviamente, faz
parte do gameplay e não de alguma customização que deva ser feita no
cenário.

Raycast

Agora será preciso encontrar uma maneira de encontrar um alinhamento entre


o local da tela onde foi feito o click do mouse em relação ao fundo do cenário,
buscando encontrar algum objeto. Esta ação se chama Raycast, onde é
disparada uma linha imaginária a partir de um ponto em direção a algum outro
ponto pré-estabelecido, conforme implementação na Listagem 3.

Listagem 3. Raycast.
01 using UnityEngine;
02 using System.Collections;
03
04 public class ScriptPlayer : MonoBehaviour
05 {
06 // Use this for initialization
07 void Start()
08 {
09
10 }
11
12 // Update is called once per frame
13 void Update()
14 {
15 // Verificando se foi clicado com o botao esquerdo do mouse.
16 if (Input.GetMouseButtonDown(0))
17 {
18 Debug.Log("O clique funcionou!");
19
20 // Variável que receberá o objeto que a linha imaginaria
// colidir.
21 RaycastHit hit;
22 // Linha iniciada a partir do ponto onde está posicionado
// o mouse.
23 Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
24
25 if (Physics.Raycast(ray, out hit, 100f))
26 {
27 Debug.Log("O clique colidiu com um objeto!");
28 }
29 }
30 }
31 }
32

Na nova atualização do script foi inserido o código responsável por identificar


quando o click for executado sobre algum objeto. A instância hit criada a
partir do script/class RaycastHit será usada com a estrutura out no método
Physics.Raycast para o caso da linha imaginária encontrar algum objeto, ou
seja, este objeto será preenchido com o GameObejct encontrado no cenário.

Relacionado: Como criar o primeiro game com Unity 3D


A variável ray - instância de Ray - é a linha imaginária criada a partir da
localização do mouse. Já que a Unity é um software de construção de jogos,
utilizando um ambiente 3D para a criação dos mesmos, todos os objetos do
cenário serão posicionados tridimensionalmente, assim, a propriedade
Position encontrada em todos os componentes Transform será instância do
script/class Vector3 (um vetor de 3 posições: x, y, z). O método
ScreenPointToRay fará a conversão do mousePosition (Vector3) para o tipo
Ray. Este método é encontrado na propriedade main do script/class Camera, o
qual faz referência direta à câmera que estiver na Scene setada com a tag
MainCamera, conforme Figura 23.

Figura 23. Tag MainCamera

A nova estrutura if adicionada ao script está verificando se em uma distância


de 100 metros (unidade de medida utilizada pela Unity) foi encontrado algum
GameObject. Mais uma vez temos a linha de comando Debug.Log com uma
mensagem para podermos testar se está tudo funcionando. Podemos retornar à
interface da Unity, clicar em Play e testar novamente o click do mouse sobre a
tela de jogo. Caso o click seja executado sobre o objeto, será escrito no
Console a mensagem "O clique colidiu com um objeto!", conforme Figura
24.

Figura 24. Console (Testando Raycast)

Como pode ser visto na Figura 23, o uso de uma tag para identificar a
câmera, agora será criada uma nova tag chamado Enemy, com o intuito de
identificar com apenas uma palavra os dois tipos de inimigos que existem no
projeto. Caso houvesse mais do que dois tipos, como é normal em jogos, o uso
de tags seria cada vez imprescindível.

Para criar uma nova tag é preciso selecionar algum GameObject presente na


Scene ou na aba Project. Já que definiremos uma tag para os inimigos,
selecionaremos um dos dois Prefabs e clicaremos na caixa de opções ao lado
da palavra tag no Inspector - logo abaixo do nome do objeto -, na qual deve
estar aparecendo por padrão a palavra Untagged (sem tag). Ao clicar sobre a
caixa surgirão algumas opções previamente criadas pela própria Unity. No
caso do projeto deste artigo, deve-se clicar na opção Add Tag,
conforme Figura 25.

Figura 25. Add Tag

Ao clicar em Add Tag surgirá no Inspector o TagManager - um local para


incluir, editar e excluir tags. O conjunto de tags não mais é do que um array,
assim, adicione a palavra Enemy na posição 0 do array (Element 0),
conforme Figura 26.

Figura 26. Criando uma nova Tag

Após a criação da tag, clique novamente em um dos Prefabs e selecione a


nova tag Enemy. Faça o mesmo para o outro Prefab. O resultado de um dos
dois Prefabs de inimigos pode ser visto na Figura 27.

Figura 27. Setando uma Tag ao GameObject

Retornando ao ScriptPlayer, pode-se identificar agora se o objeto com que


raycast colidiu é um dos inimigos através do objeto hit criado anteriormente.
Este objeto será uma representação de colisão com um GameObject, logo,
podemos encontrar entre suas propriedade o componente Transform e
consequentemente a tag, conforme Listagem 4. Se for encontrado o inimigo,
vamos criar uma lógica que randomize uma nova posição para o mesmo
dentro dos limites possíveis para o tamanho de tela definido, utilizando o
script/class Random do namespace UnityEngine.

Listagem 4. Tag e Random.


01 using UnityEngine;
02 using System.Collections;
03
04 public class ScriptPlayer : MonoBehaviour
05 {
06 // Use this for initialization
07 void Start()
08 {
09
10 }
11
12 // Update is called once per frame
13 void Update()
14 {
15 // Verificando se foi clicado com o botao esquerdo do mouse.
16 if (Input.GetMouseButtonDown(0))
17 {
18 Debug.Log("O clique funcionou!");
19
20 // Variavel que recebera o objeto que a linha
// imaginaria colidir.
21 RaycastHit hit;
22 // Linha iniciada a partir do ponto onde está posicionado
// o mouse.
23 Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
24
25 if (Physics.Raycast(ray, out hit, 100f))
26 {
27 // Verificando se objeto tem a tag Enemy.
28 if (hit.transform.tag == "Enemy")
29 {
30 // Gerando uma nova posição.
31 Vector3 newPosition = new Vector3(Random.Range(-6, 6),
Random.Range(-4, 4), 0);
32 // Setando para o objeto colidido a nova posição.
33 hit.transform.position = newPosition;
34
35 Debug.Log("O clique colidiu com um inimigo!");
36 }
37 }
38 }
39 }
40 }

Existe na Unity a possibilidade de alterarmos através da interface ou em


tempo de execução as variáveis de um script. Para isto, basta declararmos
estas variáveis como públicas. Ao ser feito isto, teremos no Inspector onde se
encontra o script as variáveis disponíveis para edição, conforme atualização
realizada no script (Listagem 5) e visualizada na interface da Unity, conforme
a Figura 28. É importante entender que alterações feitas diretamente na
interface afetarão o comportamento do script, mas não atualizarão os valores
previamente declarados quando da criação das variáveis. Aproveitando a
mudança no script, foram retiradas as linhas de escrita no Console e excluído
o método Start que não está sendo utilizado.

Listagem 5. Declarando variáveis públicas.


01 using UnityEngine;
02 using System.Collections;
03
04 public class ScriptPlayer : MonoBehaviour
05 {
06 // Essa variável permitirá a edição da tag via interface.
07 public string tagName;
08 // Comprimento da distância do ray que será usado no raycast.
09 public float rayDistance = 0;
10
11 // Update is called once per frame.
12 void Update()
13 {
14 // Verificando se foi clicado com o botao esquerdo do mouse.
15 if (Input.GetMouseButtonDown(0))
16 {
17 // Variável que recebera o objeto que a linha
// imaginaria colidir.
18 RaycastHit hit;
19 // Linha iniciada a partir do ponto onde está
// posicionado o mouse.
20 Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
21
22 // Verifica se o ray encontrará algum collider no cenário.
23 if (Physics.Raycast(ray, out hit, rayDistance))
24 {
25 // Verificando se objeto tem a tag Enemy.
26 if (hit.transform.tag == tagName)
27 {
28 // Gerando uma nova posição.
29 Vector3 newPosition =
new Vector3(Random.Range(-6, 6),
Random.Range(-4, 4), 0);
30 hit.transform.position = newPosition;
31 }
32 }
33 }
34 }
35 }

Figura 28. Expondo variáveis


Na Figura 28 é possível visualizar as variáveis criadas como públicas sendo
expostas na interface. Com isso, é possível testar diretamente via interface
como ficará o jogo. Este é um recurso muito importante para equipes que
desenvolvem jogos, pois o programador pode oferecer diversos scripts para
um game ou level designer construir as fases do jogo. Assim, quem construirá
a fase não precisa obrigatoriamente conhecer programação, somente como
utilizar os componentes pré-existentes na ferramenta e o novos que estão
sendo criados, por exemplo, o ScriptPlayer. É importante não se esquecer de
setar algum valor para a variável rayDistance, pois a mesma não tem valor no
código.

Vamos agora abrir o script ScriptEnemy e incrementar valor à jogabilidade:


primeiramente vamos alterar a forma de interação dos clicks do mouse,
setando que o objeto inimigo em tela muda de posição a cada dois clicks,
conforme Listagem 6.

Listagem 6. Script Enemy.


01 using UnityEngine;
02 using System.Collections;
03
04 public class ScriptEnemy : MonoBehaviour
05 {
06 // Controlora o numero de clicks.
07 public int numberOfClicks = 2;
08
09 // Update is called once per frame.
10 void Update()
11 {
12 // Se foi clicado mais de duas vezes.
13 if (numberOfClicks <= 0)
14 {
15 // Gerando uma nova posição.
16 Vector3 newPosition = new Vector3(Random.Range(-6, 6),
17 Random.Range(-4, 4), 0);
18 transform.position = newPosition;
19
20 numberOfClicks = 2;
21 }
22 }
23 }
Agora, o ScriptEnemy no método Update tem uma verificação sobre uma
variável pública (numberOfClicks) quantificando os clicks sobre o objeto.
Caso tenham ocorrido dois ou mais clicks, será randomizada uma nova
posição para o objeto dentro dos limites da tela. Já que a implementação está
neste método, a verificação para ver se atende a comparação do if ocorrerá
aproximadamente 60 vezes por segundo.

O passo agora é adicionar o ScriptEnemy como novo componente dos


Prefabs: PrefabEnemyCircle e PrefabsEnenySquare, simplesmente arrastando
o script sobre eles na aba Project. O resultado final pode ser visto no Inspector
de um dos dois Prefabs, conforme Figura 29.

Figura 29. ScriptEnemy aplicado ao Prefab

Para esta nova implementação funcionar é preciso alterar o ScriptPlayer, pois


anteriormente ele estava randomizando a cada click o posicionamento do
objeto em tela. A alteração que será realizada neste script detectará a colisão
com o objeto, consultará o ScriptEnemy do objeto em questão e decrementará
a variável numberOfClicks, conforme Listagem 7.

Listagem 7. Alterando o Script Player.


01 using UnityEngine;
02 using System.Collections;
03
04 public class ScriptPlayer : MonoBehaviour
05 {
06 // Essa variável permitirá a edição da tag via interface.
07 public string tagName;
08 // Comprimento da distância do ray que será usado no raycast.
09 public float rayDistance = 0;
10
11 // Update is called once per frame.
12 void Update()
13 {
14 // Verificando se foi clicado com o botao esquerdo do mouse.
15 if (Input.GetMouseButtonDown(0))
16 {
17 // Variável que recebera o objeto que a linha
// imaginaria colidir.
18 RaycastHit hit;
19 // Linha iniciada a partir do ponto onde está
// posicionado o mouse.
20 Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
21
22 // Verifica se o ray encontrará algum collider no cenário.
23 if (Physics.Raycast(ray, out hit, rayDistance))
24 {
25 // Verificando se objeto tem a tag Enemy.
26 if (hit.transform.tag == tagName)
27 {
28 ScriptEnemy script = hit.transform.GetComponent
<ScriptEnemy();
29 script.numberOfClicks--;
30 }
31 }
32 }
33 }
34 }

No ScriptPlayer, anteriormente tínhamos dentro da cláusula if que compara o


nome da tag a randomização dos inimigos, mas agora há a recuperação do
ScriptEnemy, anexado ao GameObject que foi colidido, através do método
GetComponent, o qual consegue recuperar a partir de um GameObject ou
Transform qualquer componente. Caso o componente solicitado não faça
parte do objeto, a execução do script será interrompida. Um detalhe
importante é que dentro dos scripts de programação a variável transform
assume a papel de gameObject por muitas vezes, pois o componente
Transform é obrigatório e todos os objetos terão, por isso é possível recuperar
os componentes do objeto através de métodos da propriedades transform.

Retornando à interface da Unity, vamos posicionar os dois Prefabs na aba


Scene, onde o PrefabEnemySquare será posicionado em x: 0, y: 1 e z: 0,
enquanto o PrefabEnemyCircle em x: 0, y: -1 e z: 0, resultando no que se
pode ver na Figura 30.

Figura 30. Prefabs no cenário

Já é possível testar o jogo e verificar que a cada dois clicks sobre cada um dos
objetos randomizará uma nova posição para o mesmo.

Será adicionado ao ScriptEnemy um tempo de respawn, ou seja, a cada dois


clicks além de randomizada uma nova posição, teremos um tempo de espera
para o mesmo reaparecer, conforme pode ser visto na Listagem 8.
Listagem 7. Respawn Enemy.
01 using UnityEngine;
02 using System.Collections;
03
04 public class ScriptEnemy : MonoBehaviour
05 {
06 // Controlora o numero de clicks.
07 public int numberOfClicks = 2;
08 // Tempo para o respawn do inimigo.
09 public float respawnWaitTime = 2f;
10
11 // Update is called once per frame.
12 void Update()
13 {
14 // Se foi clicado mais de duas vezes.
15 if (numberOfClicks <= 0)
16 {
17 // Disparando uma corotina (thread) para
// gerenciar o tempo de respawn.
18 StartCoroutine(RespawnWaitTime());
19
20 // Gerando uma nova posição.
21 Vector3 newPosition = new Vector3(Random.Range(-6, 6),
22 Random.Range(-4, 4), 0);
23 transform.position = newPosition;
24
25 numberOfClicks = 2;
26 }
27 }
28
29 // Sera usado para esconder por um tempo o game object.
30 IEnumerator RespawnWaitTime()
31 {
32 renderer.enabled = false;
33
34 yield return new WaitForSeconds(respawnWaitTime);
35
36 renderer.enabled = true;
37 }
38 }

O ScriptEnemy recebeu a implementação de um novo método chamado


RespawnWaitTime, onde seu retorno é um IEnumerator e dentro dele o
componente renderer é inicialmente desabilitado (com isso, o mesh do objeto
não será desenhado, tornando-o invisível), em seguida um comando para
aguardar durante o tempo definido na variável respawnWaitTime) e por fim
habilitar novamente o renderer.

Programando em C# na Unity, quando precisarmos disparar um corotina, é


preciso utilizar dos seguintes recursos:

 Ter um método que retorne IEnumerator, pois dessa forma o


compilador entenderá que existe uma sub-rotina sendo executada e a
mesma não estará bloqueando o fluxo normal de execução;
 No método criado deve existir a instrução yield, pois a mesma indicará
o uso de um iterador, que no caso é retorno ininterrupto do ciclo de
máquina enquanto no método não foi atendido o solicitado. No caso do
método criado, seria aguardar por dois segundos. Ao final desse tempo
a sub-rotina será "livre" e continuará sua execução nas linhas abaixo;
 Por fim, para fazer a chamada de um método de corotina, utilizaremos
o método StartCourotine passando o método criado, conforme podemos
ver na Listagem 7 no método Update, após atender a cláusula if que
compara os clicks.

Seguindo adiante, iremos adicionar um pequeno efeito com transição de cores


para cada vez que o objeto for randomizado em tela. Aqueles materiais que
foram criados no início do artigo e adicionados a cada um dos Prefabs agora
serão utilizados para alterarmos as cores dos objetos.

Será criado um novo método - RandomColor - dentro do ScriptEnemy para


selecionar uma cor aleatoriamente dentro de um array de cores pré-definidas.
A cada respawn do objeto será feita uma chamada para esse método,
conforme Listagem 9.

Listagem 9. Random Color.


01 using UnityEngine;
02 using System.Collections;
03
04 public class ScriptEnemy : MonoBehaviour
05 {
06 // Controlora o numero de clicks.
07 public int numberOfClicks = 2;
08 // Tempo para o respawn do inimigo.
09 public float respawnWaitTime = 2f;
10 // Quantidade de pontos do inimigo.
11 public int enemyPoints = 1;
12
13 // Array de cores.
14 private Color[] shapeColor = { Color.blue, Color.red,
Color.green, Color.yellow, Color.magenta };
15
16 // Update is called once per frame.
17 void Update()
18 {
19 // Se foi clicado mais de duas vezes.
20 if (numberOfClicks <= 0)
21 {
22 // Disparando uma corotina (thread) para
// gerenciar o tempo de respawn.
23 StartCoroutine(RespawnWaitTime());
24
25 // Gerando uma nova posição.
26 Vector3 newPosition = new Vector3(Random.Range(-6, 6),
27 Random.Range(-4, 4), 0);
28 transform.position = newPosition;
29
30 numberOfClicks = 2;
31 }
32 }
33
34 // Sera usado para esconder por um tempo o game object.
35 IEnumerator RespawnWaitTime()
36 {
37 renderer.enabled = false;
38 yield return new WaitForSeconds(respawnWaitTime);
39
40 // Randomizando a cor.
41 RandomColor();
42 renderer.enabled = true;
43 }
44
45 // Randomizando cores para mudar o material do game object.
46 private void RandomColor()
47 {
48 int index = Random.Range(0, shapeColor.Length);
49 renderer.material.color = shapeColor[index];
50 }
51 }

Na atualização do ScriptEnemy temos um array de cores setado


como private e no método RespawnWaitTime a chamada para o novo método.
No último comando do método RandomColor temos a alteração da cor do
objeto, o qual encontra-se dentro da propriedade material, que está dentro do
componente renderer. Então, é importante entender que praticamente tudo que
alterarmos via programação pode ser editado via interface e vice-versa.
Na Figura 31 podemos visualizar o material que estamos alterando no
Inspector do PrefabEnemySquare.

Figura 31. Mesh Renderer -> Material -> Color

Perceba que também foi adicionado um valor padrão de 1 para uma nova
variável chamada enemyPoints (utilizaremos a mesma mais à frente). Com a
adição do tempo para respawn e randomização de cores, pode-se novamente
testar o jogo, o qual terá uma visualização semelhante à Figura 32.

Figura 32. Testando o jogo com novas cores

Com o ScriptEnemy finalizado, retornaremos para o ScriptPlayer para criar


um contador de pontos para incrementar os clicks realizados corretamente
sobre os objetos. Através da inclusão de uma nova variável do tipo int
chamada score controlaremos o incremento da pontuação a cada dois clicks do
jogador sobre o objeto, conforme Listagem 10, utilizando a variável
enemyPoints criada anteriormente. Através da edição desta variável pelo
Inspector dos Prefabs, podemos alterar a quantidade pontos para que um ou
dois possam valer, ou seja, isso é uma decisão de projeto.

Listagem 10. Calculando o score.


01 using UnityEngine;
02 using System.Collections;
03
04 public class ScriptPlayer : MonoBehaviour
05 {
06 // Essa variável permitirá a edição da tag via interface.
07 public string tagName;
08 // Comprimento da distância do ray que será usado no raycast.
09 public float rayDistance = 0;
10 // Contador de pontos.
11 public int score = 0;
12
13 // Update is called once per frame.
14 void Update()
15 {
16 // Verificando se foi clicado com o botao esquerdo do mouse.
17 if (Input.GetMouseButtonDown(0))
18 {
19 // Variável que recebera o objeto que a linha
// imaginaria colidir.
20 RaycastHit hit;
21 // Linha iniciada a partir do ponto onde está
// posicionado o mouse.
22 Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
23
24 // Verifica se o ray encontrará algum collider no cenário.
25 if (Physics.Raycast(ray, out hit, rayDistance))
26 {
27 // Verificando se objeto tem a tag Enemy.
28 if (hit.transform.tag == tagName)
29 {
30 ScriptEnemy script = hit.transform.GetComponent
<ScriptEnemy();
31 script.numberOfClicks--;
32
33 if (script.numberOfClicks == 0)
34 {
35 score += script.enemyPoints;
36 }
37 }
38 }
39 }
40 }
41 }
Adicionaremos ao ScriptPlayer um contador de tempo para o jogo, onde
criaremos uma variável do tipo float que será decrementada a cada segundo.
Para isso, utilizaremos o método InvokeRepeating do framework, o qual nos
permite definir de quanto em quanto tempo um método será chamado,
conforme Listagem 11.

Listagem 11. Count Down.


01 using UnityEngine;
02 using System.Collections;
03
04 public class ScriptPlayer : MonoBehaviour
05 {
06 // Essa variável permitirá a edição da tag via interface.
07 public string tagName;
08 // Comprimento da distância do ray que será usado no raycast.
09 public float rayDistance = 0;
10 // Contador de pontos.
11 public int score = 0;
12 // Contador de tempo para contabilizar quanto tempo durara o jogo.
13 public float gameTime = 20f;
14
15 void Start()
16 {
17 // Definindo o metodo que sera chamado a cada 1 segundo.
18 InvokeRepeating("CountDown", 1f, 1f);
19 }
20
21 // Update is called once per frame.
22 void Update()
23 {
24 // Verificando se foi clicado com o botao esquerdo do mouse.
25 if (Input.GetMouseButtonDown(0))
26 {
27 // Variável que recebera o objeto que a linha
// imaginaria colidir.
28 RaycastHit hit;
29 // Linha iniciada a partir do ponto onde está posicionado
// o mouse.
30 Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
31
32 // Verifica se o ray encontrará algum collider no cenário.
33 if (Physics.Raycast(ray, out hit, rayDistance))
34 {
35 // Verificando se objeto tem a tag Enemy.
36 if (hit.transform.tag == tagName)
37 {
38 ScriptEnemy script =
hit.transform.GetComponent<ScriptEnemy();
39 script.numberOfClicks--;
40
41 if (script.numberOfClicks == 0)
42 {
43 score += script.enemyPoints;
44 }
45 }
46 }
47 }
48 }
49
50 private void CountDown()
51 {
52 // Subtraindo o tempo de jogo.
53 gameTime--;
54 // Se chegar a zero, cancela a chamada do metodo.
55 if (gameTime == 0)
56 {
57 CancelInvoke("CountDown");
58 }
59 }
60 }

Se o jogo for testado novamente e estivermos com a Main Camera


selecionada na aba Hierarchy, poderemos ver na aba Inspector a variável
Game Time sendo decrementada a cada segundo até chegar a zero.

Nas definições do que é jogo encontraremos que ele é feito de feedbacks


visuais e aurais. No caso dos visuais, seriam todas as imagens projetadas na
tela de jogo que ofereçam ao jogador o status do jogo ou mesmo alertas sobre
acontecimento que acontecerem ou estão por vir. Então, criaremos dentro do
ScriptPlayer um GUI (Graphic User Interface) para escrever em tela o valor
atual do score e do tempo restante de jogo.

Todas as escritas de textos que envolvem GUI serão executadas dentro de um


método específico chamado OnGUI, conforme Listagem 12.

Listagem 12. Escrevendo na GUI.


01 using UnityEngine;
02 using System.Collections;
03
04 public class ScriptPlayer : MonoBehaviour
05 {
06 // Essa variável permitirá a edição da tag via interface.
07 public string tagName;
08 // Comprimento da distância do ray que será usado no raycast.
09 public float rayDistance = 0;
10 // Contador de pontos.
11 public int score = 0;
12 // Contador de tempo para contabilizar quanto tempo durara o jogo.
13 public float gameTime = 20f;
14
15 void Start()
16 {
17 // Definindo o metodo que sera chamado a cada 1 segundo.
18 InvokeRepeating("CountDown", 1f, 1f);
19 }
20
21 // Update is called once per frame.
22 void Update()
23 {
24 // Verificando se foi clicado com o botao esquerdo do mouse.
25 if (Input.GetMouseButtonDown(0))
26 {
27 // Variável que recebera o objeto que a linha
// imaginaria colidir.
28 RaycastHit hit;
29 // Linha iniciada a partir do ponto onde está posicionado
// o mouse.
30 Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
31
32 // Verifica se o ray encontrará algum collider no cenário.
33 if (Physics.Raycast(ray, out hit, rayDistance))
34 {
35 // Verificando se objeto tem a tag Enemy.
36 if (hit.transform.tag == tagName)
37 {
38 ScriptEnemy script = hit.transform.GetComponent
<ScriptEnemy();
39 script.numberOfClicks--;
40
41 if (script.numberOfClicks == 0)
42 {
43 score += script.enemyPoints;
44 }
45 }
46 }
47 }
48 }
49
50 private void CountDown()
51 {
52 // Subtraindo o tempo de jogo.
53 gameTime--;
54 // Se chegar a zero, cancela a chamada do metodo.
55 if (gameTime == 0)
56 {
57 CancelInvoke("CountDown");
58 }
59 }
60
61 void OnGUI()
62 {
63 GUI.Label(new Rect(10, 10, 120, 40), "Score: " + score);
64 GUI.Label(new Rect(10, 30, 120, 40), "Time: " + gameTime);
65 }

No método OnGUI, que será executado na mesma parcela de vezes que o


Update, estaremos escrevendo na tela dois labels. O primeiro deles é a
pontuação do jogo e o segundo o tempo de jogo. Para definirmos em tela
algum tipo de GUI, precisamos sempre definir em que posição ele estará e o
espaço que ocupará; isso é feito através do script/class Rect, ou seja,
definimos um retângulo em tela a partir da esquerda e do alto e depois a
largura e altura. Algo semelhante ao CSS (Cascading Style Sheet) utilizado na
web.

Após salvar a Scene atual (SceneGameLevel), vamos criar uma nova cena que
será o menu inicial do jogo clicando no menu superior em File -> New Scene,
conforme Figura 33.

Figura 33. New Scene

Nesta nova cena faremos o seguinte para prepará-la para ser o menu inicial:

 Selecionar a Main Camera e editá-la no Inspector da mesma forma que


editamos a câmera na SceneGameLevel, conforme Figura 18. O
resultado da câmera na aba Scene será um visão ortográfica, de
tamanho 5 e distância 20, conforme Figura 34;
 Anexar o script nomeado como ScriptScreenMainMenu à câmera,
apenas arrastando-o sobre o objeto;
 Abrir o ScriptScreenMainMenu para edição no MonoDevelop, onde o
resultado será o apresentado na Listagem 13.

Figura 34. Scene View -> Main Camera

Listagem 13. ScriptScreenMainMenu.
01 using UnityEngine;
02 using System.Collections;
03
04 public class ScriptScreenMainMenu : MonoBehaviour
05 {
06 void OnGUI()
07 {
08 if (GUI.Button(new Rect(10, 10, 120, 40), "Start Game"))
09 {
10 Application.LoadLevel("SceneGameLevel");
11 }
12 if (GUI.Button(new Rect(10, 70, 120, 40), "Exit Game"))
13 {
14 Application.Quit();
15 }
16 }
17 }

Novamente temos o uso do método OnGUI, onde foram incluídos dois botões
em tela. Os dois são posicionados através do script/class Rect e setados seus
valores no segundo parâmetro do método: Start Game e Exit Game. O método
GUI.Button executa duas funções: uma delas seria a de escrever o texto no
botão e a segunda seria a detecção de algum click sobre ele. No caso do click
no botão Start Game, teremos a chamada ao método Application.LoadLevel
que carregará a scene setada no seu parâmetro. No caso de click no botão Exit
Game teremos a chamada ao método Apllication.Quit, que fecha o jogo.

Depois de concluído esta etapa, devemos salvar a nova cena (Ctrl + S),
nomeando-a SceneScreenMainMenu, conforme Figura 35.

Figura 35. Scene Screen Main Menu

Antes de testarmos, vamos nos adiantar e criar duas novas cenas para o jogo:

 SceneScreenWin;
 SceneScreenLose.

Elas serão utilizadas para representar vitória e derrota do jogador. Crie-as


conforme foram criadas as anteriores, editando suas câmeras e anexando os
scripts ScriptScreenWin e ScriptScreenLose às câmeras de suas cenas
respectivas.

Agora sim, para testarmos a transição entre as telas, precisamos entender o


processo de build da Unity.

Builds

Em qualquer momento da criação do jogo se pode ver como o jogo ficará no


seu formato final, ou seja, podemos testá-lo fora do editor da Unity. Através
do menu superior File -> Build Settings teremos acesso a uma janela de ajuda,
onde podemos definir para qual plataforma será realizado o build do jogo,
conforme Figura 36.

Figura 36. Build Settings

A primeira vez que for acessando esta janela em um projeto, ela irá aparecer
com Scenes in Build vazia. Se o jogo for construído com essa lista vazia,
apenas a Scene que estiver aberta no momento será incluída no Build. Se
desejarmos construir rapidamente uma execução de teste com apenas um
único arquivo Scene, bastar construir com a lista de Scene vazia mesmo.

Para adicionar os arquivos de Scene à lista para builds, basta selecioná-la na


aba Project e arrastá-la para dentro da caixa Scenes in Build, conforme Figura
37.

Figura 37. Scenes in Build

Nesse ponto, observe que cada uma das Scenes tem um valor diferente de
índice. A Scene 0 será a primeira Scene que carregada quando o jogo for
executado fora o editor da engine. Como já mostrado anteriormente, para
carregar uma nova Scene, utiliza-se o comando Application.LoadLevel a
partir de algum scripts.

Se for adicionado mais de um arquivo de Scene e for necessário reorganizá-


los, basta simplesmente clicar e arrastar para cima ou para baixo na lista até
que se tenha a ordem desejada.

Para remover uma Scene da lista, clique para destacar a Scene e pressione a
tecla Delete. A Scene irá desaparecer da lista e não será incluída no build.

Quando o jogo estiver pronto para ser publicado, selecionaremos uma


Platform (Plataforma). Finalmente pressionaremos o botão Build (Construir).
Em seguida, selecionaremos o nome e a localização do jogo usando uma
janela de salvar arquivos padrão. Quando clicarmos em Save (Salvar), a Unity
irá construir o jogo prontamente.

Para testar a transição de Scenes também é preciso adicioná-las na caixa de


Scenes In Build. Após isso, clique no Play e teste clicar no botão Start
Game e ver o jogo carregar a SceneGameLevel.

Para finalizar o jogo vamos implementar o scripts de vitória e derrota que


serão utilizados nas últimas duas Scenes criadas, conforme Listagens 14 e 15.

Listagem 14. ScriptScreenWin.
01 using UnityEngine;
02 using System.Collections;
03
04 public class ScriptScreenWin : MonoBehaviour
05 {
06 void OnGUI()
07 {
08 GUI.Label(new Rect(10, 10, 120, 40), "YOU WIN!!!");
09
10 if (GUI.Button(new Rect(10, 70, 120, 40), "Restart Game"))
11 {
12 Application.LoadLevel("SceneGameLevel");
13 }
14 if (GUI.Button(new Rect(10, 140, 120, 40), "Exit Game"))
15 {
16 Application.Quit();
17 }
18 }
19 }

Listagem 15. ScriptScreenLose.
01 using UnityEngine;
02 using System.Collections;
03
04 public class ScriptScreenLose : MonoBehaviour
05 {
06 void OnGUI()
07 {
08 GUI.Label(new Rect(10, 10, 120, 40), "YOU LOSE!!!");
09
10 if (GUI.Button(new Rect(10, 70, 120, 40), "Restart Game"))
11 {
12 Application.LoadLevel("SceneGameLevel");
13 }
14 if (GUI.Button(new Rect(10, 140, 120, 40), "Exit Game"))
15 {
16 Application.Quit();
17 }
18 }
19 }

Perceba que os códigos são semelhantes ao script do menu, apenas com a


adição de um label com a mensagem de vitória ou derrota, a reestruturação da
altura inicial do posicionamento dos botões e o primeiro botão como Restart
Game.
Com todas as Scenes implementadas, vamos retornar ao ScriptPlayer e
adicionar ao final do tempo de jogo uma condição de verificação para o
jogador vencer ou perder o jogo, conforme Listagem 16.

Listagem 16. Condição de vitória e derrota.


01 using UnityEngine;
02 using System.Collections;
03
04 public class ScriptPlayer : MonoBehaviour
05 {
06 // Essa variável permitirá a edição da tag via interface.
07 public string tagName;
08 // Comprimento da distância do ray que será usado no raycast.
09 public float rayDistance = 0;
10 // Contador de pontos.
11 public int score = 0;
12 // Contador de tempo para contabilizar quanto tempo durara o jogo.
13 public float gameTime = 20f;
14 // Quantidade de pontos para a vitória.
15 public int numberOfPointsToWin = 10;
16
17 void Start()
18 {
19 ...
20 }
21
22 // Update is called once per frame.
23 void Update()
24 {
25 ...
26 }
27
28 private void CountDown()
29 {
30 // Subtraindo o tempo de jogo.
31 gameTime--;
32 // Se chegar a zero, cancela a chamada do metodo.
33 if (gameTime == 0)
34 {
35 CancelInvoke("CountDown");
36
37 if (score >= numberOfPointsToWin)
38 {
39 Application.LoadLevel("SceneScreenWin");
40 }
41 else
42 {
43 Application.LoadLevel("SceneScreenLose");
44 }
45 }
46 }
47
48 void OnGUI()
49 {
50 ...
51 }
52 }

No método CountDown, ao final do tempo de jogo, foi adicionada uma


comparação onde a pontuação obtida for igual ou superior à quantidade
necessária (nova variável numberOfPointsToWin) será carrega a tela de
vitória, do contrário a tela de derrota.

Se desejar, na opção Build Settings, faça o build do jogo em diferentes


plataformas e veja o resultado.

Enfim, temos nosso jogo finalizado. Por mais simples que seja o gameplay do
jogo construído, a intenção deste artigo foi a de apresentar a ferramenta e os
conceitos que envolvem a criação de um jogo. Ainda, explorar um pouco do
C# para o desenvolvimento na Unity.

Conclusão

A Unity 3D é uma poderosa ferramenta para criação de jogos e com ela vem
uma infinidade de recursos para elaboração dos mesmos. Este artigo teve o
intuito de apresentar para os apaixonados por jogos que é possível criar os
seus próprios com a ajuda de uma interface amigável, que nos facilita em
diversos pontos do desenvolvimento, caso quiséssemos fazer tudo “na mão”.
Toda a parte de LoopGame, desenho e renderização gráfica já está embutida
no software, além da outros recursos não abordados aqui, como sistemas de
partículas, efeitos de luz e sombra, áudio, entre outros. A área de criação de
jogos no Brasil ainda engatinha, mas se for do interesse do leitor de ingressar
nesse ramo ou pelo menos conhecer, existem diversos tutoriais disponíveis
pela internet e com pouco esforço é possível encontrar alguns bastante
profissionais.

Você também pode gostar