Ponto V!

Home Unity Visão Geral do Unity
Bruno Xavier
Visão Geral do UnityImprimir
Escrito por Bruno Xavier

Com a adesão crescente de novos usuários à Unity, tanto aqui na comunidade quanto mundo á fora, busco através deste tutorial expressar uma visão geral sobre a engine, suas ferramentas e ajudar os aventureiros e curiosos a terem uma experiência prévia de uma rotina de trabalho no ambiente da ferramenta.

Unity 3D - Visão Geral_html_4b9a674a

Este tutorial é uma compilação de conceitos e conhecimentos básicos que todo desenvolvedor em Unity precisa ter antes de partir para qualquer tipo de projeto e graças à esplêndida estrutura em que a Unity é desenhada você pode facilmente produzir enquanto aprende. Pensando nisso, vejamos o que será explorado neste pequeno tutorial:

  • Entendo Assets, GameObjects e Components.
  • Importando Skinned Meshes e trabalhando com animações.
  • Conhecendo melhor o Builtin Controller Component.
  • Entendendo Unity's JavaScript, suas funções e co-rotinas.
  • Trabalhando com Classes, Helper Functions e código Frame-Dependente.
  • Colocando tudo em prática.

O que você já precisa dominar para melhor aproveitamento e entendimento deste tutorial:

  • Ser familiarizado com a interface do Unity Editor.
  • Possuir algum personagem 3D animado ou saber como produzir um em seu software de preferência.
  • Ter acesso aos guias e manuais oficiais da Unity para referência.
  • Ter um conhecimento mínimo da estrutura e programação em JavaScript.

Tela principal do Unity

Sendo assim, vamos lá:

1. Entendo Assets, GameObjects e Components:

1.1 Assets:

Assets, se você já andou explorando as funcionalidades e documentação, já deve ter em mente que os Assets são os arquivos físicos de seu projeto. Não há nenhum segredo aqui, todos os seus modelos 3D, arquivos de áudio, scripts, etc e etc que precisam ser estocados em disco são parte desta classe de seu projeto, os recursos com o qual você irá trabalhar encima de seu projeto.Assets do seu projeto

Antes que um Asset possa ser utilizado é necessário que você tenha um projeto criado e adicione o arquivo desejado dentro da pasta Asset na pasta raiz do projeto.

Uma funcionalidade incrível da Unity é que você pode trabalhar, por exemplo, em suas cenas 3D e apenas clicando save no modelador o resultado é automaticamente atualizado na Unity, você apenas assiste a engine re-compilando a cena e logo em seguida o resultado pode ser facilmente visualizado no Scene View.

Dê uma olhada no guia básico da Unity para um melhor entendimento.

1.2 GameObjects:

Game Objects da cena atual

Todo objeto que faz parte do mundo 3D de sua cena e possui um Component “Transform” é um GameObject. Um Transform é apenas um componente ligado ao objeto que indica que o mesmo tem volume, escala ou apenas se localiza em algum ponto no mundo 3D de sua cena, são as básicas informações XYZ. Ao trabalhar na Unity, você geralmente usa um Asset como base para criar seu GameObject e com o auxilio de Components vai adicionando funcionalidades, com o GameObject implementado da maneira que você deseja, é sempre boa prática converter o GameObject em um Prefab para melhor organização, melhor performance e facilidade de re-uso de seus objetos entre os vários leveis que pode ter o seu game.

Prefabs são outra ferramenta de destaque extremamente úteis e poderosas na Unity. Consulte a documentação para melhor informação.

1.3 Componentes

Componentes de um Game Object

Sem eles é impossível dar vida á qualquer objeto que faça parte de seu cenário. Os Components são a essência de como as coisas na Unity funcionam, são a maior expressão das facilidades de trabalho que a engine oferece. Scripts são Components, objetos e efeitos de física, partículas, áudio e etc são todos Components que podem ser adicionados ao seu GameObject para faze-lo se comportar dar maneira que você deseja no game. É importantíssimo ter uma visão clara de como os Components funcionam e como se relacionam entre si.

Mais sobre isso será falado durante a seção de programação, mas se você sente que não entende realmente o que exatamente são essas coisas, procure pensar que Components são “Itens” que formam um item ainda maior, seu objeto na cena, e que eles controlam todas as características do objeto no game. Um GameObject sem Components é um objeto sem característica alguma, por isso não pode ser manipulado de forma alguma e provavelmente é um objeto inútil para o seu projeto neste ponto.

Simplificando, Components são propriedades que tornam seus GameObjects únicos através da combinação entre as ferramentas providas pela Unity e os Assets que você produz. É assim justo dizer que quanto melhor forem os Assets que você produz, melhores serão seus GameObjects e maiores as capacidades de seus Components de realizar exatamente tudo que você deseja extrair deles.

2. Importando Skinned Meshes e trabalhando com animações

Você já conhece bem a interface da Unity e agora tem um entendimento mais claro dos como e por quê seus objetos funcionam. Sendo assim, partiremos para um pequeno experimento prático, importar um personagem animado e dar funcionalidade á ele.

2.1 O Personagem

Personagem usado como exemplo

Se você não possui um personagem animado, divirta-se, crie um! :)

Para este personagem em questão que eu usarei, existem algumas notas que devem estar em mente.

Eu tenho a intenção de utilizar efeitos de física real no personagem, por isso neste caso há duas versões dele, uma sem Skin com todas as partes do corpo separadas em pedaços para serem adicionadas componentes físicos e gerar um efeito rápido e fácil diferenciado de “ragdoll” onde o personagem explode ao morrer.

E a versão convencional com a Skin e animações como de costume.

Este é um caso específico do meu trabalho em questão, você não é obrigado a fazer um personagem da mesma maneira, use sua liberdade e imaginação.

2.2 Implementando o Personagem

Personagem já no Unity

Por motivos de Pipeline, já utilizo o formato FBX á um bom tempo, eu continuo usando FBX mesmo na Unity, por conveniência.

Você pode utilizar o formato que preferir e se adaptar melhor.

Bom, após um tempo relativamente grande, você modelou, texturizou, animou seu querido personagem e está pronto pra faze-lo mandar ver na Unity. Apesar das facilidades que a Unity oferece, você precisa ter em mente que certas convenções devem ser seguidas.

Antes de qualquer coisa, adicione seu modelo em qualquer diretório dentro da pasta Assets do seu projeto, a Unity irá detectar o arquivo e ele aparecerá na lista do Inspector com todas suas opções de importação. Não mecha em absolutamente nada, click e arraste o modelo da lista do Project View para a Scene View e veja o que acontece. Seu personagem aparece na cena sem problemas? Ótimo, você é um cara de sorte! Click Play e rode o game, veja se as animações rodam normalmente como esperado.

As animações estão ok? Ótimo, você é mesmo um cara de sorte! :)

Ao arrastar o personagem para a cena, ele está distorcido, como se os bones não estivessem nas posições corretas ou coisa semelhante? Opa, volte ao seu modelador 3D e reveja seus conceitos, evite criar uma hierarquia muito complexa de parents e childs, grupos e sub grupos quando se trata de um personagem animado.

Ao arrastar o personagem para a cena, o modelo parece estar ok, mas as animações simplesmente não tocam ou existe algo de errado com elas, como se suas animações não estivessem ali?

Opa, volte ao seu modelador 3D e reveja novamente seus conceitos, se você tem conhecimento básico sobre animação deve saber que as animações de controladores e parentes dos bones, efeitos físicos, driven keys e etc, não são automaticamente adicionados aos bones do seu modelo no momento da exportação, por isso, se for o caso de haver animações faltando ou animações faltando pedaços, você precisa ter certeza de que todos os movimentos que faz está gerando animation keys nos bones do personagem ou seja, você precisa usar a solução “Bake Animations”. Você pode fazer isso diretamente na Unity simplesmente acionando a check-box de mesmo nome no Importer do seu modelo ou se quiser mais controle sobre os resultados, faça isso você mesmo no modelador, os resultados são mais fáceis de serem mantidos da maneira que você exatamente quer. Se você não sabe como fazer um “bake” em suas animações, consulte a documentação do seu programa ou peça socorro á comunidade lá no fórum da Unity, sempre tem alguém perguntando sobre este tipo de problema.

No geral, clicando em Bake Animations na Unity vai resolver seus problemas e muita dor de cabeça se você não gosta de ficar horas otimizando keys no seu modelador 3D.

Após ajustadas as configurações de importação, seu personagem é animado da maneira que você espera? Ótimo, é hora de prepara-lo para o futuro que o reserva, no Importer do seu modelo, clicando no arquivo importado no Project View ficará visível no Inspector, você verá que existe uma variedade grande de opções e propriedades. Seja um bom amigo com você mesmo e pesquise na documentação cada uma dessas características e opções para ter uma visão mais intuitiva e verdadeira do que cada uma delas possa vir a ser.

Mais abaixo no Inspector, existe um pequeno grupo que é acionado quando você seleciona a opção “Split Animations”. Click nessa opção e você terá acesso a ferramenta mais simples da terra para criar clips de animações. Você pode dar um nome aos clips e definir o início e fim da animação, seu WrapMode e etc de maneira rápida, fácil e visual.

Neste ponto, é extremamente recomendável criar um Prefab para seguir seu trabalho, você não pode trabalhar diretamente encima do Asset do seu personagem por isso é boa prática criar um GameObject com seu personagem, apenas arraste ele do Project View para a Scene View, no menu Assets click em Create New > Prefab, renomeie o Prefab com o nome que quiser e arraste seu personagem da Scene View para cima do Prefab. Pronto, você tem uma instância totalmente reutilizável do seu personagem em que qualquer mudança no Inspector afetará todas as cópias do objeto em sua cena.

Após configurar seus clips, seu personagem está pronto para ser animado in-game... Mas hey, e agora? Como se anima o personagem, pergunta-se o afobado aprendiz...

A resposta para isso se resume á uma palavra – Scripts!

Mas antes, precisamos ter uma ideia mais aprofundada do que exatamente vamos animar. É uma boa hora para pesquisar sobre o Character Controller Component!

3. Conhecendo melhor o Builtin Controller Component

Unity 3D - Visão Geral_html_1b95013d

Á primeira vista você deve estar imaginando que este componente é responsável pelo controle das animações de seu personagem durante a execução de seu game, certo... Errado! :P

O Component responsável pelas animações, você já passou por ele, seus Animation Clips estão prontos, lembra? A partir daí você pode animar seu personagem através de qualquer script; Mas é interessante analisar a relação restrita entre o Controller, que controla a interatividade entre o jogador e a jogabilidade estabelecida por você, no caso o controle do personagem em questão. O Controller Component existe para facilitar a sua vida na hora de identificar ações e inputs tanto do player quanto do ambiente que cerca seu personagem para uma interação funcional mais rápida prática e intuitiva.

Sem essa belezinha você teria deliciosas dores de cabeça para conseguir fazer seu personagem interagir com o resto dos objetos no game e responder aos comandos do jogador. Existe também uma variação mais complexa de Controller, totalmente baseada em física real, mas é um tópico muito nex-gen e avançado demais pra mim no momento e não é meu foco neste tutorial, vamos examinar inicialmente o Controller básico. Se você ainda não leu a respeito deste componente na documentação, esta é a hora.

Após ler a documentação, você agora deve saber bem que um Controller basicamente permite que você dê interatividade ao objeto em que o Component está ligado de maneira que esse objeto interaja com o ambiente físico ao redor. Baseado neste fundamento, você pode ter certeza, se você nunca trabalhou com física real antes, ou você aprende um pouco sobre física ou aprende muito sobre física por que a Unity se aproveita ao máximo de todas as formas de manipulação física e estudar um pouco a respeito desta matéria é bastante saudável para facilitar sua vida. Na Unity você irá programar como nunca voltado á interatividade com física real, mesmo que o componente em questão não seja baseado em física. Por mais que seja um tanto incômodo precisar fazer certos cálculos para atingir certos resultados por conta da física, cedo ou tarde você acaba percebendo que esta forma de trabalho diminui de maneira gritante a quantidade de código que você precisa para realizar efeitos complexos e poderosos de mesmo nível que qualquer game comercial existente no mercado.

Não vou entrar em extremos detalhes aqui por que seria redundante ficar citando o que já é muito bem explicado na documentação, mas ao trabalhar com Character Controllers, tome sempre um cuidado especial com Physical Materials e com as propriedades do Controller, Height e Skin Width.

É aconselhável sempre manter a propriedade “Min Move Distance” em zero, a não ser que você tenha mesmo um bom motivo para não faze-lo.

Todos scripts que forem criados com intenção de manipularem a interatividade do personagem farão referência á este componente de alguma forma então, antes de prosseguir, faça os ajustes que achar necessário, experimente bastante com cada propriedade do componente e personifique da maneira que achar melhor.

Com o Controller Component adicionado ao seu personagem, ao seleciona-lo você já deve ter notado que aparece um “Capsule Collider” ligado ao mesmo. Ajuste a posição e volume do Collider da maneira que puder de modo que ele represente bem o volume geral do corpo de seu personagem.

Para testes, crie uma Box com um Collider Component, modifique sua escala e a utilize como chão, click Play e verifique se os pés de seu personagem não estão flutuando ou afundando no chão, faça os ajustes que achar necessários para ter uma colisão refinada entre seu personagem e os objetos que virem a existir no seu cenário. Quando atingir o resultado que deseja, você pode sempre adicionar as mudanças ao Prefab do Personagem se houver um. Isso afeta todas as cópias do seu Personagem, independente de qual cenário você esteja trabalhando. Após estes pequenos ajustes, estamos prontos para começar a programar.

Você pode escolher a linguagem de suporte que achar melhor, eu prefiro JavaScript :)

4. Entendendo Unity's JavaScript, suas funções e co-rotinas

Unity 3D - Visão Geral_html_m6ceef8a8

Lembre-se que a estrutura aqui é JavaScript, para C# existem pequenas diferenças que devem ser levadas em conta ao programar, se você está iniciando em Unity como eu, é extremamente recomendável começar com JavaScript ao invés de C# pois a comunidade dá muito mais suporte a JavaScript na prática.

Antes de entrarmos em detalhes, é importante ressaltar que a Unity tem como expectativa assumir que você, como programador, siga as convenções estabelecidas para programação na ferramenta. É sempre importante lembrar que a engine espera que você siga os padrões de nomenclatura para funções e variáveis, isso não é exatamente obrigatório, você pode não seguir nada disso se quiser, mas no fim das contas você apenas acaba gerando problemas a si próprio. Tendo isso em mente, vejamos as convenções adotadas na Unity mais importantes que são adotadas por toda a comunidade que busca sempre utilizar a ferramenta com eficiência e clareza.

4.1 Nomeando Funções

Quando criar uma função, lembre-se de que o nome de cada função deve começar com um caractere legal e sempre em letra maiúscula. Sabendo disso e seguindo esta padronização, lhe salvará uma vida de problemas e bugs que você mesmo escreveu e não consegue resolver pelo simples fato de não ter seguido uma convenção tão simples.

Se a função é um conjunto de várias palavras, você pode optar por usar underlines se quiser, mas é aconselhável apenas seguir o padrão, como por exemplo, MyFunctionName(). Assim quando um problema surgir no debug e apontar para um identificador, você tem certeza absoluta de que o caso se trata de uma função e não qualquer outro tipo de dados.

4.2 Nomeando Variáveis

Assim como na criação de uma função, é boa prática seguir o padrão estabelecido pela comunidade e desenvolvedores da engine, a simples diferença aqui é que nomes para variáveis sempre devem iniciar com um caractere legal em letra minúscula. Exemplo, minhaVariavel : int;

4.3 Funções

Este ponto é onde a coisa pode complicar de início para programadores que não estão acostumados a seguir o tipo de lógica adotado na Unity. A engine, por padrão, faz todo o trabalho sujo de controle do software, execução, loops, carregos e despejos, etc e etc. Sendo assim, ela trabalha com funções padronizadas que todos os scripts que você escreva irão utilizar uma ou outra de alguma forma.

Por exemplo, na Unity você não cria um loop principal para a execução do seu game, pois ele já está lá antes mesmo de você começar a programar. Você apenas precisa chamar uma “instância” da função responsável pelo loop, no caso Update().

Isso vai parecer muito confuso no início, você começa a se perguntar, ao criar vários scripts com a mesma função, “qual desses updates é o principal?”... O caso é que toda função que você criar com o nome de Update(), serão todas ao mesmo tempo o seu loop principal. Não me pergunte como a engine faz isso, mas ao compilar seus scripts a Unity detecta todas as instâncias das funções com nome que ela já conhece, transforma todas as funções em uma única função e seu código está pronto para rodar. O que é ainda mais incrível é que ela faz isso mesmo com seu projeto aberto no editor, não é necessário compilar nada, a engine faz tudo sozinha, você apenas clica Play!

Vejamos uma relação das funções e métodos padronizados mais importantes que você usará com frequência:

4.4 Function Awake(){...}:

Essa função, se existente em seu script, é executada sempre que o script é carregado na memória. Mesmo que você não a chame em momento algum, essa função será sempre executada, basta declara-la e todas as ações que você definir na função serão executadas imediatamente no mesmo momento em que o GameObject que contém o script for carregado. Não se faz uma chamada para esse tipo de função, ela apenas é declarada.

Geralmente essa função é utilizada somente para captura de valores para variáveis recém-declaradas. Consulte a documentação para maiores informações.

4.5 Function Start(){...}:

Essa função, se existente em seu script, não é executada assim que seu script é carregado, mas ela atua de maneira muito interessante.

Você não precisa chamar esta função de lugar algum, ela será automaticamente executada uma única vez antes que qualquer loop do seu script seja executado pela primeira vez, ou seja, antes do primeiro loop.

4.6 Function Update(){...}:

Essa função, se existente em seu script, é sempre executada á cada frame. Você não precisa fazer nenhum tipo de referência ou chamada, ela apenas será executada como forma de loop principal do seu script, não necessariamente do seu programa, mas de tudo que é executado no script em questão.

4.7 Function FixedUpdate(){...}:

Essa função é uma variante de Update(), é um loop dedicado á proporcionar melhor funcionalidade para qualquer efeito diretamente ligado á RigidBodies. Você pode tanto ter uma FixedUpdate() quanto uma Update() no mesmo script, os loops diretamente ligados á execução do game são sempre interligados entre si e a execução de um loop não interfere na execução de outro.

4.8 Function LateUpdate(){...}:

Essa função, também variante de Update() é um loop para chamada específica de ações que você deseja executar somente quando todas as instancias de Update() já foram executadas. É muito útil para a implementação de animações via script, restrições de movimento ou posição de objetos, etc.

Existem muitos outros loops pré-determinados pela Unity sempre estabelecidos de maneira que possam agilizar seu trabalho. Consulte a documentação e pesquise sobre loops distintos existentes em várias classes da engine. Procure se familiarizar com a relação geral desses loops entre si, mas concentre-se apenas em dominar as funções descritas acima, sem um domínio claro do uso dessas funções e de como elas podem ser utilizadas em seu projeto, todo o resto se torna uma pilha de informações sem sentido no momento em que você for programar qualquer coisa com a Unity.

5. Trabalhando com Classes, Helper Functions e código Frame-Dependente

Unity 3D - Visão Geral_html_3aab4818

Um fato curioso sobre trabalhar com a Unity é que você vai precisar utilizar classes em casos relativamente raros em seu projeto, ao contrário de muitas outras engines ou plataformas existentes por aí. Isso se dá pelo fato de que a Unity é tão bem projetada que qualquer coisa que você queira criar provavelmente já se encaixa como descendente de alguma classe já existente na Unity então a criação de classes em seu game raramente se tornará uma rotina.

Apesar disso, existem casos em que a criação de classes será extremamente útil e tornará seu script muito mais maleável e poderoso. O uso de classes também pode facilitar a leitura de seu código, tornando sua escrita mais elegante e muito bem organizada de modo que em um trabalho feito por uma equipe, a criação de co-rotinas por outro programador fica muito agradável de forma que seu colega não precisa realmente dominar totalmente todos os pormenores da classe que você escreveu. Helper functions, co-rotinas, são inicialmente uma ferramenta chave para manter a organização de seu código, tornando-o ainda mais legível que de costume e ajuda a facilitar a procura por bugs que cedo ou tarde inevitavelmente acabam surgindo durante sua produção. Outra característica importante sobre co-rotinas é que elas abrem um outro leque de possibilidades como as tão importantes funções dependentes de tempo ou frame-rate.

5.1 Classes

A Unity já disponibiliza uma lista robusta de classes que você usa e abusa, mas é interessante ter a possibilidade de criar classes customizadas inteiramente dedicadas á um tipo específico de objeto em seu game, por exemplo, uma classe dedicada somente ao controle do seu personagem, outra classe dedicada somente á execução de animações do personagem, outra classe que ativa triggers que otimizam a interatividade de seu personagem com o ambiente, etc.

5.2 Helper Functions

A primeira funcionalidade de importância real que você vai encontrar para o uso obrigatório deste tipo de funções é a possibilidade de utilizar, a partir dessas co-rotinas, funções que derivam da classe “Yield”. Funções do tipo Yield não podem ser chamadas de loops principais como Update() por que elas tem como característica interromper a execução do loop, veja bem, do loop que chama a função, não seu programa como um todo.

Essa distinção pouco comum entre funções na Unity proporciona uma maleabilidade incrível na manipulação de seu código. Você pode interromper partes da execução de um loop enquanto que outra parte do mesmo loop pode continuar sendo executada normalmente. Tal funcionalidade é muito útil para muitas situações que possam surgir, mas com certeza este tipo de função é largamente utilizado para um controle preciso e refinamento de animações e timing que você irá se deparar cedo ou tarde.

5.3 Código Frame-Dependente

A Unity já disponibiliza funções plenas para manipulação e checagem de tempo que estão sempre a disposição para lhe dar suporte no momento em que precisar. Se você não está acostumado a utilizar o conceito de Delta-Time, consulte a documentação da classe “Time” na referência de scripting. Você vai encontrar variáveis muito úteis como Time.deltaTime que podem facilitar suas animações via script de maneira suave e limpa.

6. Colocando tudo em prática

Unity 3D - Visão Geral_html_m68f6501c

Agora que já temos uma visão mais ampla das características da engine que envolvem a implementação de um personagem interativo na Unity, vamos arregaçar as mangas e botar as mãos na massa! :)

Nota: Meu projeto em particular se trata de um platformer, e no site da Unity você pode encontrar muito material de referência que estou usando como guia base tanto para este tutorial quanto para o desenvolvimento do meu projeto pessoal. Sinta-se sempre compelido a baixar tudo que o site da Unity oferece e examine de cabo á rabo todos os scripts que caírem em suas mãos. No tutorial básico para um 2D Platformer, você poderá perceber que existem muitas funções implementadas pelo Flashbang Studios que também são usadas aqui de forma muito semelhante, se não idênticas em alguns casos.

Lembre-se de que nem tudo se trata de autoria, muita coisa se trata de pesquisa. Não trate o hábito de pesquisar como algo ruim, isso apenas vai lhe impedir de compartilhar com gente muito mais experiente e com conhecimento muito mais profundo do que o seu. Mantenha a mente aberta! :)

6.1 Importe o Asset de seu personagem

Crie um GameObject, crie um Prefab e estamos prontos para começar a botar as ideias em prática. Por enquanto não se preocupe com esse Prefab, apenas seguimos em frente com nosso personagem existente na cena.

6.2 Crie uma pasta no Project View

Após criar a paste, renomeie para Scripts. Em seguida, selecione essa mesma pasta, vá até Assets > Create > JavaScript. Um script descendente da classe MonoBehavior será criado na paste selecionada. Selecione o script criado e renomeie com o mesmo nome de seu personagem, apenas para melhor organização.

6.3 Criando um Componente

Agora que já temos um Component que podemos trabalhar encima de nosso personagem, na Hierarchy View selecione seu personagem, vá até Components > Create New > NomeDeSeuScript. Notou como o script que criou aparece instantaneamente no menu? Coisa linda não? Selecione o script de seu personagem, preste atenção nas propriedades no Inspector de seu personagem, ele agora também lista o componente recém-adicionado.

Seu Script é um componente como qualquer outro ligado ao personagem, se quiser você pode aplicar as mudanças do GameObject ao seu Prefab.

Selecione a opção Edit no Component Script de seu personagem ou dê um duplo clique no script no Project View, a Unity irá iniciar seu editor padrão para a edição de scripts. Você pode utilizar qualquer editor que quiser para isso, o editor de scripts é sempre um programa externo, você pode também customizar de modo forçado as opções do editor padrão, mas isso já é conteúdo para um outro tutorial, nos manteremos focados ao que realmente importa aqui.

6.4 Editando um Script

Ao abrir seu script para edição, por padrão a Unity já o cria com uma função Update() vazia. Isso, por enquanto, não é muito útil. Agora, vamos parar e pensar um pouco... O que queremos fazer aqui?

“-Bota essa budega pra funfá, e para de blahblah”, diz o afoito aprendiz.

Bom, sem entendermos bem o que exatamente queremos fazer, não será possível fazermos exatamente nada de útil ou conciso então vamos nos concentrar em um único conceito e trabalhar encima disso...

Controle de Personagem? Animação? GamePlay?
Tá legal vamos animar nosso personagem, já que isso parece ser o mais lógico a ser feito primeiro, ao menos é mais lógico para mim.

Em seu script, selecione a função Update() vazia e apague. Não precisamos dela agora. Primeiro vamos pensar de modo genérico sobre as ações de nosso personagem. O que ele irá fazer no game? Vai andar? Correr? Pular? Etc.

Com isso em mente, já temos algo por onde começar, hora de começar a cuspir variáveis que achamos que podem ser úteis. Lembre-se, se você não conhece um mínimo de JavaScript, ao menos a syntax, você pode ter experiências desagradáveis ao programar. Tenha certeza de que já se sente confortável com a programação nesta linguagem e que sua syntax não pareça algo alienígena. Sendo assim, vamos lá. Criando as variáveis:

var sneakAnimationSpeedModifier = 1.5;

var walkAnimationSpeedModifier = 2.5;

var runAnimationSpeedModifier = 1.5;

var jumpAnimationSpeedModifier = 2.0;

var jumpLandAnimationSpeedModifier = 3.0;

var getDownAnimationSpeedModifier = 1.5;

var hangTimeUntilFallingAnimation = 0.05;

private var floorHitFX : AudioClip;

Cada variável tem um propósito, conforme descrito a seguir:

  • sneakAnimationSpeedModifier: Usaremos esta variável para um controle mais ágil da velocidade em que a animação “Sneak” será executada.
  • walkAnimationSpeedModifier: Usaremos esta variável para controlar a velocidade em que a animação “Walk” será executada.
  • runAnimationSpeedModifier: Usaremos esta variável para controlar a velocidade em que a animação “Run” será executada.
  • jumpAnimationSpeedModifier: Usaremos esta variável para controlar a velocidade em que a animação “Jump” será executada.
  • jumpLandAnimationSpeedModifier: Usaremos esta variável para controlar a velocidade em que as animações “Landing” e “Landed” serão executadas.
  • getDownAnimationSpeedModifier: Usaremos esta variável para controlar a velocidade em que a animação “Get Down” será executada.
  • hangTimeUntilFallingAnimation: Usaremos esta variável para identificar quanto tempo faz que o personagem está em queda livre.
  • floorHitFX: Usaremos esta variável do tipo AudioClip para guardar um pointer para o som que queremos tocar quando o personagem atinge o chão de maneira descontrolada. Se isso parecer confuso, consulte a classe AudioClip na documentação.

A regra “private”, ao contrário do que parece, não isola sua variável contra acesso de outros scripts. Na verdade deveria, mas sempre existe alguma maneira de acessar uma variável privada se preciso, então é apenas uma questão de isolar a variável para que ela não esteja amostra no Inspector.

Após definir suas variáveis, selecione seu personagem ou Prefab, observe no Inspector como elas se tornaram parte das propriedades do seu script. Essa funcionalidade do Inspector é sem palavras, torna seu trabalho tão dinâmico.

6.5 Implementando o Personagem

Agora que temos nossas variáveis, podemos trabalhar encima disso, dando á elas as funcionalidades que buscamos. Com o conceito de controle de nossas animações em mente, vamos iniciar a estrutura básica que coloca em prática os clips de animações que criamos anteriormente na importação do Asset do personagem:

function Start() {
    animation.Stop();
    var jumpingLayer = 1;
    var afterJumpLayer = 2;
    var jump = animation["Jump"];

    jump.layer = jumpingLayer;
    jump.speed *= jumpAnimationSpeedModifier;

    var jumpFall = animation["Small Fall"];
    jumpFall.layer = jumpingLayer;

    var freeFall = animation["Fall"];
    freeFall.layer = afterJumpLayer;

    var fallImpact = animation["Floor Impact"];
    fallImpact.layer = afterJumpLayer;
    fallImpact.speed *= 3;

    var fallGetUp = animation["Get Up"];
    fallGetUp.layer = afterJumpLayer;
    fallGetUp.speed *= 0.95;

    var stayJumping = animation["Stay Jumping"];
    stayJumping.layer = afterJumpLayer;

    var jumpLanding = animation["Landing"];
    jumpLanding.layer = afterJumpLayer;
    jumpLanding.speed *= jumpLandAnimationSpeedModifier*2.5;

    var jumpLand = animation["Landed"];
    jumpLand.layer = jumpingLayer;
    jumpLand.speed *= jumpLandAnimationSpeedModifier;

    var run = animation["Run"];
    run.speed *= runAnimationSpeedModifier;

    var walk = animation["Walk"];
    walk.speed *= walkAnimationSpeedModifier;

    var sneak = animation["Sneak"];
    sneak.speed *= sneakAnimationSpeedModifier;

    var getDown = animation["Get Down"];
    getDown.speed *= getDownAnimationSpeedModifier;

    var smallImpact = animation["Small Impact"];
    smallImpact.layer = afterJumpLayer;
}

Note que este bloco de código apenas inicializa as variáveis com os valores desejados. Isso poderia ser feito em qualquer ponto fora da função Start(), mas como queremos ter certeza de que as variáveis serão inicializadas antes que qualquer loop comece a rodar, inicializamos as variáveis desta forma.

6.6 Trabalhando com Animações não Procedurais

Trabalhar com animações não procedurais é relativamente simples, então tudo que precisamos é de um punhado de ações e reações controlados por mais um punhado de estruturas baseadas em Cases ou Ifs. Com nossas variáveis inicializadas, só nos resta implementar os resultados no personagem durante a execução do game, então devemos trabalhar na função Update(). Antes disso, criaremos algumas co-rotinas que podem auxiliar algumas tarefas durante a execução das animações:

function DidJump() {
    animation.Play("Jump");
    animation.PlayQueued("Small Fall");
    yield WaitForSeconds(0.225);
    if (Input.GetButton("Jump"))
    {
        animation.CrossFade("Stay Jumping");
    } else {
        if (GetComponent(PlayerController).isFalling == false)
        {
            animation.CrossFade("Small Fall");
        } else {
            animation.Play("Fall");
        }
    }
    yield WaitForSeconds(0.015);
    GetComponent(PlayerController).canControl = false;
}

function DidLand() {
    if (GetComponent(PlayerController).isFalling == false)
    {
        if (animation.IsPlaying("Stay Jumping"))
        {
            animation.Play("Landing");
        } else {
            animation.CrossFade("Landed");
        }
        yield WaitForSeconds(0.15);
        GetComponent(PlayerController).canControl = true;
    } else {
        animation.CrossFade("Floor Impact");
        animation.CrossFade("Get Up");
        GetComponent(PlayerController).isFalling = false;
        yield WaitForSeconds(0.15);
        GetComponent(PlayerController).canControl = true;
    }
}

Sobre a função DidJump(): Esta função será utilizada pelo script PlayerController que criaremos logo depois. Basicamente, essa função checa o estado da animação atual e executa a animação desejada assim que o script PlayerController decidir que é o momento certo para estas animações serem executadas.

Sobre a função DidLand(): Sempre que o script PlayerController detectar que o personagem pousou de um salto ou caiu em algum lugar, ele irá enviar uma mensagem para este script dizendo que o personagem acabou de atingir o solo e a animação de pouso deve ser tocada.

Ao salvar seu script, neste ponto a Unity vai estar se indagando o que viria a ser o componente “PlayerController”. Este é um script que ainda não criamos, por isso seu código ainda não funciona, mas agora precisamos definir a função Update() e então podemos partir para o script que a Unity acusa estar faltando.

6.7 Editando a função Update

Na função Update() nós continuamos o trabalho com as animações, mas com a diferença de que não poderá ser usada nenhuma função “Yield” aqui:

function Update() {
    if (GetComponent(PlayerController).GetHangTime() < hangTimeUntilFallingAnimation)
    {
        if (GetComponent(PlayerController).headsUp == false)
        {
            if (GetComponent(PlayerController).IsMoving())
            {
                if (Input.GetButton("Action A"))
                {
                    if (GetComponent(PlayerController).isSneaking != true)
                    {
                        animation.CrossFade ("Run");
                    } 
                    else 
                    {
                        animation.CrossFade("Sneak");
                    }
                } 
                else 
                {
                    if(Input.GetAxis("Vertical") <= -0.25)
                    {
                        animation.CrossFade("Sneak");
                        GetComponent(PlayerController).isSneaking = true;
                    } 
                    else 
                    {
                        animation.CrossFade ("Walk");
                        GetComponent(PlayerController).isSneaking = false;
                    }
                }
            } 
            else 
            {
                if (GetComponent(PlayerController).headsUp == true)
                {
                    animation.CrossFade("Get Down");
                    GetComponent(PlayerController).isSneaking = true;
                } 
                else 
                {
                    if (GetComponent(PlayerController).isSneaking == false)
                        animation.CrossFade("Idle");
                }
            }
            if (!GetComponent(PlayerController).IsMoving())
            {
                if (Input.GetAxis("Vertical") <= -0.25)
                {
                    animation.CrossFade("Get Down");
                    GetComponent(PlayerController).isSneaking = true;
                } 
                else 
                {
                    GetComponent(PlayerController).isSneaking = false;
                }
            }
        } 
        else 
        {
            GetComponent(PlayerController).isSneaking = true;
            if (GetComponent(PlayerController).IsMoving() == false)
            {
                animation.CrossFade("Get Down",0.5);
            } 
            else 
            {
                animation.CrossFade("Sneak",0.5);
            }
        }
    } 
    else 
    {
        if (!GetComponent(PlayerController).isSneaking == true)
            animation.CrossFade("Landed");
    }
}

E assim nossas animações estão prontas para desempenhar seu papel no game.

Nessa função existe conteúdo suficiente para um bom tempo de estudo. Deixando um pouco de lado a mecânica de nossas animações, vamos dar uma olhada mais de perto em o que exatamente estas linhas estão fazendo:

Antes de tudo, nós verificamos se o personagem não está caindo á tempo suficiente para impedir sua movimentação terrena, e se caso não o estiver, seguimos em frente com as animações, caso contrário significa que precisamos tocar a animação de pouso pois muito em breve ele irá tocar o solo. Verificamos isso através da função GetHangTime() que escreveremos no futuro.

Em seguida, verificamos se o personagem não colidiu com algum obstáculo que o force à se manter agachado através da variável headsUp. A implementação desta funcionalidade pode se tornar complexa pois envolve alguns conceitos que talvez não sejam cobertos aqui, por isso talvez seja matéria de um outro tutorial no futuro, quem sabe.

Se o personagem estiver ciente de que há algo sobre sua cabeça que o impede de levantar, ele será obrigado à se mover agachado, caso contrário se o botão de corrida estiver pressionado ele poderá correr, caso contrário eles apenas irá andar normalmente. Assim nós tocamos a animação de correr ou andar ou engatinhar somente se o personagem está mesmo se movendo, julgando isso através da função IsMoving() que ainda não foi escrita.

Note que as teclas virtuais do meu projeto tem nomes próprios ao invés do padrão criado pela Unity.

Se você precisar editar suas teclas virtuais, vá até Edit > Project Settings > Input.

6.8 PlayerController

Partiremos agora para o lado interativo que controla nossas animações com o script PlayerController.

Vá até o menu Assets e crie mais um JavaScript, renomeio para “PlayerController”, adicione-o como componente do seu personagem, aplique as mudanças ao Prefab e estamos prontos para programar. Novamente, começamos com a declaração de variáveis:

var movement : PlatformerControllerMovement;
var jump : PlatformerControllerJumping;
private var controller : CharacterController;
var canControl = true;
var spawnPoint : Transform;
var floorHitFX : AudioClip;

@System.NonSerialized
var isSneaking = false;

@System.NonSerialized
var isFalling = false;

@System.NonSerialized
var headsUp = false;

As variáveis são usadas para:

  • movement: Usaremos esta variável como identificador para a classe que determina os movimentos do personagem.
  • jump: Usaremos esta variável como identificador para a classe que controla toda mecânica do movimento de pulo do personagem.
  • controller: criamos aqui uma instância do Builtin Controller Component que deve ser adicionado ao personagem. Você pode adicionar a linha “ @script RequireComponent(CharacterController) ” ao fim de seu script e assim que ele for adicionado á um objeto, o componente requerido também será adicionado.
  • canControl: Usaremos esta variável para permitir ou não que o personagem possa ser controlado pelo jogador. Isso é muito útil para evitar que o jogador consigo executar movimentos muito irreais como por exemplo, saltar para a esquerda e de repente ainda no ar virar e começar a cair para a direita. É também muito útil para a criação de cut-scenes.
  • spawnPoint: O conceito de Spawn Point é interessante. Quando seu personagem morrer, entrar em alguma passagem, túnel, portas, etc, esse conceito é extremamente útil para facilitar a sua vida na hora de tele-portar um personagem para o local de destino. Esta variável nada mais é do que uma coordenada qualquer em seu espaço 3D para onde o personagem pode ser movido.
  • floorHitFX: Já criamos uma variável de mesmo nome em nosso primeiro script. Ela faz referência ao clipe de som que usaremos aqui para ser usado como efeito de quando o personagem atinge o chão de maneira brusca. Não se pode esquecer de assinar um Audio Clip da sua lista de Assets. Se você não tiver nenhum áudio á mão, pode baixar alguns de sites frees pela web ou pode apenas ignorar esta questão do tutorial.
  • isSneaking: Esta variável se torna verdadeira todas as vezes em que um objeto que faz parte da layer escolhida se sobrepõem sobre a cabeça do personagem em determinada altura que o impeça de se manter de pé. Infelizmente os cálculos usados para fazer o personagem entender que precisa se manter agachado são um tanto fora do foco e fazem parte de outros scripts que detectam colisões e raycasts, por isso pode complicar o entendimento e desviar a atenção, então deixaremos este tópico para um outro tutorial.
  • isFalling: Esta variável deve se tornar verdadeira todas as vezes em que o personagem estiver caindo de uma altura exagerada ou saltar de forma descontrolada, indicando que ele sofrerá uma queda dolorosa ao invés de um pouso comum. Esta funcionalidade utiliza os mesmos princípios básicos que isSneaking, mas é apenas uma regra simples dentro do próprio loop Update() que executa um raycast em direção ao solo e se a altura for muita, o personagem sofrerá uma queda ao atingir o solo.
  • headsUp: Esta variável deve se tornar verdadeira todas as vezes que o raycast implementado por outro script na cabeça do personagem indicar que existe um objeto muito próximo que o impede se manter de pé. Faz parte do sistema que identifica se ele está agachado ou não. Esta variável é usada como um gatilho que força o personagem a se abaixar mesmo contra a vontade do jogador enquanto ele não se afastar do obstáculo que o impede de se manter de pé.

6.9 Classes Auxiliares

Com nossas variáveis bem definidas, podemos seguir em frente com a implementação de nossas classes que auxiliarão na programação de toda a movimentação de nosso personagem:

class PlatformerControllerMovement
{
    var walkSpeed = 3.0;
    var runSpeed = 10.0;
    var inAirControlAcceleration = 1.0;
    var gravity = 60.0;
    var maxFallSpeed = 20.0;
    var speedSmoothing = 5.0;
    var rotationSmoothing = 5.0;

    @System.NonSerialized
    var direction = Vector3.zero;

    @System.NonSerialized
    var verticalSpeed = 0.0;

    @System.NonSerialized
    var speed = 0.0;

    @System.NonSerialized
    var isMoving = false;

    @System.NonSerialized
    var collisionFlags : CollisionFlags;

    @System.NonSerialized
    var velocity : Vector3;

    @System.NonSerialized
    var inAirVelocity = Vector3.zero;

    @System.NonSerialized
    var hangTime = 0.0;

    var sneakControllerHeight : float = 0.95;
    var sneakControllerCenter : Vector3 = Vector3(0,0.5,0);
}

class PlatformerControllerJumping
{
    var enabled = true;
    var height = 1.0;
    var extraHeight = 4.1;

    @System.NonSerialized
    var repeatTime = 0.05;

    @System.NonSerialized
    var timeout = 0.15;

    @System.NonSerialized
    var jumping = false;
    
    @System.NonSerialized
    var reachedApex = false;

    @System.NonSerialized
    var lastButtonTime = -10.0;

    @System.NonSerialized
    var lastTime = -1.0;

    @System.NonSerialized
    var lastStartHeight = 0.0;
}

Sobre nossas classes:

Ao salvar seu script, você pode ver que todas as variáveis expostas das classes aparecem de maneira elegante e organizada no Inspector.

Não existem mais tantas dúvidas sobre a funcionalidade das animações, então não há necessidade de informação redundante. O que estas irão fazer é simplesmente pegar as informações que o player insere através de valores seja em um gamepad ou teclado e implementar a interatividade, mandando mensagens nos momentos certos para que as animações sigam a lógica definida pela interatividade proposta. Neste momento em diante a questão de jogabilidade vai se tornando cada vez mais presente e você se ver por horas e horas aprimorando a movimentação e Gameplay de seu personagem. Em uma situação assim com tantas variáveis co-relacionadas é sempre bom utilizar uma classe para tornar o trabalho menos doloroso.

Com nossas classes definidas, vamos em frente em trabalhar com o conteúdo oferecido por elas:

function Awake()
{
    movement.direction = transform.TransformDirection(Vector3.forward);
    controller = GetComponent(CharacterController);
    Spawn();
}

function FixedUpdate()
{
    transform.position.z = 0;
}

function Update()
{
    if (isDying != true)
    {
        if (Input.GetButtonDown ("Jump") && canControl) 
        {
            jump.lastButtonTime = Time.time;
        }
        UpdateSmoothedMovementDirection();
        ApplyGravity();
        ApplyJumping();

        lastPosition = transform.position;
        var currentMovementOffset = movement.direction * movement.speed + Vector3 (0, movement.verticalSpeed, 0) + movement.inAirVelocity;
        currentMovementOffset *= Time.deltaTime;

        movement.collisionFlags = controller.Move (currentMovementOffset);
        movement.velocity = (transform.position - lastPosition) / Time.deltaTime;

        if (movement.direction.sqrMagnitude > 0.01)
            transform.rotation = Quaternion.Slerp (transform.rotation, Quaternion.LookRotation (movement.direction), Time.deltaTime * movement.rotationSmoothing);

        if (controller.isGrounded) 
        {
            movement.inAirVelocity = Vector3.zero;
            if (jump.jumping) 
            {
                jump.jumping = false;
                SendMessage ("DidLand", SendMessageOptions.DontRequireReceiver);
                var jumpMoveDirection = movement.direction * movement.speed + movement.inAirVelocity;

                if (jumpMoveDirection.sqrMagnitude > 0.01)
                    movement.direction = jumpMoveDirection.normalized;
            }
        }

        UpdateEffects ();
        if (isSneaking == true)
        {
            if (controller.height != movement.sneakControllerHeight) {controller.height = movement.sneakControllerHeight;}
            if (controller.center != movement.sneakControllerCenter) {controller.center = movement.sneakControllerCenter;}
        } 
        else 
        {
            if (headsUp == false)
            {
                if (controller.height != 1.85) {controller.height = 1.85;}
                if (controller.center != Vector3(0,0.98,0)) {controller.center = Vector3(0,0.98,0);}
            }
        }

        var hit : RaycastHit;
        var floorRect = transform.TransformDirection(Vector3(0,-1,0));

        if (Physics.Raycast(transform.position,floorRect,hit))
        {
            if (hit.distance >= 6.5)
            {
                isFalling = true;
            }
        }

        if (isFalling == true)
        {
            if (Input.GetButton("Jump"))
            {
                if (jump.enabled == true)
                {
                    animation.Stop("Fall");
                    animation.CrossFade("Stay Jumping");
                    isFalling = false;
                }
            }
        }
    }
}

function UpdateSmoothedMovementDirection()
{ 
    var h = Input.GetAxisRaw ("Horizontal");
    if (!canControl)
        h = 0.0;

    movement.isMoving = Mathf.Abs (h) > 0.1;
    if (movement.isMoving)
        movement.direction = Vector3 (h, 0, 0);

    if (controller.isGrounded)
    {
        var curSmooth = movement.speedSmoothing * Time.deltaTime;
        var targetSpeed = Mathf.Min (Mathf.Abs(h), 1.0);
        if (isSneaking == false && headsUp == false)
        {
            if (Input.GetButton ("Action A") && canControl)
            {
                targetSpeed *= movement.runSpeed;
            } 
            else 
            {
                targetSpeed *= movement.walkSpeed;
            }
        } 
        else 
        {
            targetSpeed *= movement.walkSpeed;
        }

        movement.speed = Mathf.Lerp (movement.speed, targetSpeed, curSmooth);
        movement.hangTime = 0.0;
    }
    else 
    {
        movement.hangTime += Time.deltaTime;
        if (movement.isMoving)
            movement.inAirVelocity += Vector3 (Mathf.Sign(h), 0, 0) * Time.deltaTime * movement.inAirControlAcceleration;
    }
}

function Spawn()
{
    movement.verticalSpeed = 0.0;
    movement.speed = 0.0;
    if (respawnPoint != null)
    {
        transform.position = respawnPoint.position;
    }
}

function ApplyGravity()
{
    var jumpButton = Input.GetButton ("Jump");
    if (!canControl)
        jumpButton = false;

    if (jump.jumping && !jump.reachedApex && movement.verticalSpeed <= 0.0) 
    {
        jump.reachedApex = true;

        SendMessage ("DidJumpReachApex", SendMessageOptions.DontRequireReceiver);
    }

    var extraPowerJump = jump.jumping && movement.verticalSpeed > 0.0 && jumpButton && transform.position.y < jump.lastStartHeight + jump.extraHeight && !IsTouchingCeiling ();
    if (extraPowerJump)
        return;
    else if (controller.isGrounded)
        movement.verticalSpeed = -movement.gravity * Time.deltaTime;
    else
        movement.verticalSpeed -= movement.gravity * Time.deltaTime;

    movement.verticalSpeed = Mathf.Max (movement.verticalSpeed, -movement.maxFallSpeed);
}

function ApplyJumping()
{
    if (isSneaking != true && headsUp != true)
    {
        if (jump.lastTime + jump.repeatTime * 15 > Time.time)
            return;

        if (controller.isGrounded) 
        { 
            if (jump.enabled && Time.time < jump.lastButtonTime + jump.timeout) 
            {
                movement.verticalSpeed = CalculateJumpVerticalSpeed (jump.height);
                SendMessage ("DidJump", SendMessageOptions.DontRequireReceiver);
            }
        }
    }
}

function CalculateJumpVerticalSpeed(targetJumpHeight : float)
{
    return Mathf.Sqrt (2 * targetJumpHeight * movement.gravity);
}

function DidJump()
{
    jump.jumping = true;
    jump.reachedApex = false;
    jump.lastTime = Time.time;
    jump.lastStartHeight = transform.position.y;
    jump.lastButtonTime = -10;
    canControl = true;
}

function GetSpeed()
{
    return movement.speed;
}

function GetVelocity()
{
    return movement.velocity;
}

function IsMoving()
{
    return movement.isMoving;
}

function IsJumping()
{
    return jump.jumping;
}

function IsTouchingCeiling()
{
    return (movement.collisionFlags & CollisionFlags.CollidedAbove) != 0;
}

function GetDirection()
{
    return movement.direction;
}

function GetHangTime()
{
    return movement.hangTime;
}

function Reset()
{
    gameObject.tag = "Player";
}

function SetControllable(controllable : boolean)
{
    canControl = controllable;
}

E assim temos ambos os scripts que controlam tanto as animações quando a jogabilidade básica do personagem como andar, correr, saltar, cair, agachar, se arrastar, etc. O script acima é uma forma de física controlada e por isso, em certos momentos, envolve muita matemática que pode ser muito confusa se você não conhecer ao menos um pouco sobre física. Ler alguns livros sobre o assunto é sempre muito útil.

A partir deste ponto, se tudo correu bem, seu personagem deve estar andando, correndo e saltando normalmente.

Unity 3D - Visão Geral_html_407a3414

É possível que você tenha talvez alguma dificuldade para executar o tutorial, se for o caso, provavelmente você ainda precisa se ambientar melhor com a interface da Unity e conhecer mais a fundo seus conceitos antes de se arriscar em animar um personagem que nesse caso pode ser uma questão complexa. Se você teve dificuldades em seguir este tutorial por não ser um passo-a-passo, é normal, este tutorial é focado em explicar “conceitos” ao invés de indicar exatamente como algo deve ser feito e por isso há muita coisa não explicada aqui que você precisa pesquisar por si próprio.

Bem, minha parte termina aqui, mas a sua está apenas começando, se você estiver mesmo disposto a por em prática os códigos exemplificados aqui, não tente apenas copiar e colar, isso definitivamente não irá funcionar. Estude com atenção, procure realmente entender o que está acontecendo em cada linha e não muito além você se verá desenvolvendo funções ainda mais poderosas e se tornando cada vez mais seguro e experiente para tentar conteúdo cada vez mais avançado.

Por exemplo, tente implementar você mesmo as funções que forçam o personagem a se manter agachado e crie objetos no cenário para testar a funcionalidade e ir aos poucos aprimorando sua função. Garanto que você vai se divertir tanto que certa hora você se verá mais jogando seu game do que trabalhando nele! Rsrsrs.

Você pode também criar obstáculos que explodam e gerem dano no seu personagem, criar uma ragdoll, etc.

Crie um script que mantenha o estado do seu personagem, como por exemplo, vidas, barra de energia, etc.

Você pode criar efeitos com partículas e aplicálos ao seu spawnPoint indicando visualmente que o personagem aparece naquele ponto, pode criar também respawnPoints onde o personagem continuará a partir dalí se caso ele morrer, etc.

Unity 3D - Visão Geral_html_m3f3ff281

Enfim, divirta-se com a Unity enquanto aprende e ao mesmo tempo produz. Acredito que isto seja o segredo de qualquer coisa que exige dedicação, faça por diversão e não por obrigação. Boa sorte!


Comentários (36)
  • Bruno Torres  - Parabéns!
    avatar

    Muito Bom seu Tutorial (Aula de Unity) hehe :lol:
    Espero nessas férias de final de ano, poder colocar em práticas algumas coisas como um personagem animado e uma UI simples.

    Ah, uma coisa seu personagem foi "rigado" com bones tipo do 3ds max ou biped? Posso usar biped ou obrigatoriamente tem quer ser os bones? ;)

    Valeu.

    Abraço!

  • Bruno Xavier
    avatar

    Obrigado Torres.
    Quanto ao rig, até o momento o Unity suporta somente bones, não suporta automaticamente rigs mais complexos. Está em endamento um sistema semelhante ao Euphoria do GTA IV pela Unity Tech, no caso utilizando Inverse Kinematics, mas por enquanto apenas bones mesmo. Abraço.

  • Bruno Torres  - Valeu
    avatar

    Hum..

    Valeu pela resposta,
    tava modelando um personagem pra testes
    então farei com bones mesmo hehe

    Muito Legal esta notícia nem fazia idéia ^^

    Muito Obrigado pela resposta..

    Aguardo mais tutoriais de Unity se possível..

    Abraço!

  • Anônimo  - Developer
    avatar

    Essa ferramenta é ótimo, pena que para fazer para Android é paga..enfim anos luz em frente do bug"XNA".. belo tutorial..

  • Bruno Crivelari Sanches
    avatar

    XNA é uma API e uma coleção de ferramentas para facilitar desenvolvimento de jogos, não uma ferramenta de autoria como o Unity. Não tem sentido comparar as duas, são duas ferramentas totalmente diferentes e que visam públicos diferentes.

    O Unity é mais comparável com UDK, CryEngine, etc.

    Agora eu acho o preço da versão Android insignificante perto dos outros custos de se fazer um jogo. É muito menos que um mês de salário de um desenvolvedor e você vai economizar muito mais que um mês com uma ferramenta dessas dependendo do projeto.

    T+

  • Mateus Pires  - Preços
    avatar

    Você tem o valor para comprar a licença para o Android?

  • Bruno Crivelari Sanches
    avatar

    Basta acessar o site e ir na loja: https://store.unity3d.com/shop/

    Pelo o que estou vendo, versão Android USS400

    T+

  • Nick
    avatar

    cara tenho uma pergunta! como fazer uma animação completa? tipo quero que ela tenha todos os movimentos e quero que ela faça coisas sobre humanas tipo voar super força, super poderes pegar objetos no chão! saco?

  • Bruno Crivelari Sanches
    avatar

    Você quer fazer animação ou implementar isso?

    Se quer que o personagem do seu jogo faça essas ações, além das animações você tem que programar esses movimentos.

  • Anônimo
    avatar

    onde baixa ?

  • Bruno Crivelari Sanches
    avatar

    http://www.unity3d.com

    T+

  • Vinícius Godoy de Mendonça
    avatar

    http://unity3d.com/unity/download/

  • dalton  - triggers
    avatar

    Bom dia Bruno.
    Uma dúvida a respeito de triggers. Eu quero fazer com que um objeto caia próximo ao meu personagem. para isso eu teria que fazer dois triggers? Um faria o objeto cair quando o personagem passar pelo trigger, é isso? Abção e parabéns pelo blog

  • Bruno Xavier
    avatar

    Olá dalton, desculpe a demora na resposta.
    Eu não entendi bem sua dúvida. programar gameplay em Unity pode ser feito de várias e várias maneiras diferentes.
    Eu faria o seguinte:
    Deixaria o objeto em modo kinematic, no RigidBody.
    Criaria um trigger collider onde o personagem deve passar como vc mesmo mencionou.
    Assim que o trigger é ativado, enviaria uma mensagem para um script no objeto que desativaria o modo kinematic do RigidBody e ele cairia encima ou proximo do personagem.
    Abraço.

  • Gustavo Antunes de Bitencourt  - Unity3D com Realidade Aumentada
    avatar

    Ola pessoal.

    Bruno, parabéns pelo post.

    Você já implementou um jogo com Unity3D com a tecnologia de Realidade Aumentada?

    Sabes me informar de que forma é melhor eu trabalhar com esse combo(RA + Unity3D) ?

    Desde já, muito obrigado.

    Abraço.

  • Bruno Xavier
    avatar

    Gustavo, mil desculpas pela resposta tãooo atrasada; Eu preciso receber alguma forma de notificação nos posts pois eu não tenho como monitorar o site constantemente.

    Então, sobre a sua pergunta: a maneira mais simples de se trabalhar com RA na Unity, em relação ao software, é através de bibliotecas de terceiros que você precisaria portar para a Unity você mesmo provavelmente.
    Infelizmente eu não sou familar com essa area e nunca tive nenhum contato com essas bibliotecas, mas acredito que devem ser plugins .NET, apenas não sei se existe alguma de código aberto. Boa sorte!

  • Gustavo Antunes de Bitencourt
    avatar

    Desculpas pela demora em dar o feedback também.
    Valeu pelas dicas e aproveitando para deixar aqui que está disponível
    a lib de NYArtoolkit para Unity3D.

    Valeu, abraço.

  • Fanuel Marinho
    avatar

    Olá Bruno,
    Parabéns pelo seu post, muito interessante e bem elaborado.
    Gosto bastante da Unity3D.

    Pelo que estava lendo, vi que você se formou na Full Sail University.
    Você não poderia fazer um post falando mais a respeito dos cursos que você fez lá , o que gostou e coisa e tal??


    Abraço

  • Bruno Xavier
    avatar

    Oi Fanuel.
    Eu posso te dar duas dicas:
    º O que eu não gostei foi o preço rsrs...
    º E também o fato de que as pessoas por lá não gostam muito de estrangeiros, por mais que tentem te convencer que sim.
    Meu inglês não é dos melhores, mas ainda assim a instituição foi bastante compreensiva.

    Os professores são gente que praticamente se poderia pedir autografos, além do conhecimento que eles passam e levam a SÉRIO, isso é muito importante, uma das coisas mais valiosas que se pode obter lá são os emails desses professores heheh.
    Existem muitos cursos, apesar de ser um pouco versado em programação eu estudei artes e game design então eu sinceramente não tenho idéia de como são os cursos de programação por lá. Minha intenção era trabalhar no mercado de CGI, mas com o tempo as oportunidades que surgiram foram com games e como eu já fazia muitas modificações nos softwares Autodesk, acabei pegando uns trabalhos envolvendo arte tecnica o que me obrigou a aprender programação mais convecional.
    Não pude ficar na região por muito tempo e quando voltei, decidi aplicar o que aprendi em jogos para estudios que publicam indie games pois eles aceitam com mais facilidade trabalhos remotos...

    Mas recomendo! Apenas o preço não é agradável; Fiz também alguns cursos específicos na Gnomon e é também fora de sério.
    Por experiência, digo que as empresas brasileiras não irão dar muito valor a uma formação destes moldes, mas com as empresas de fora você consegue muita atenção. Abraço.

  • Ráfagan
    avatar

    Olá!

    Uma dúvida. Vejo que utiliza abusivamente os recursos de captura de componentes do GameObject dentro de seu update. Pelo que eu conheço de Unity, GetComponent é reflection e, apesar de ser um recurso poderoso, é muito caro.

    Não seria mais interessante capturar as referências aos componentes dentro do awake, ao invés de realizar diversas chamadas ao GetComponent?

  • Bruno Xavier
    avatar

    Olá Rafagan. Pois é, esse texto é na verdade de 2009.
    Na época não havia muita noção de optmização em Unity inclusive por parte dos próprios desenvolvedores da engine. Hoje, como Unity cresceu demais e muita coisa foi modificada é sim impraticável usar GetComponent dentro de loops.

    Abraço.

  • Hans  - Cinematica
    avatar

    Como fasso cinematica em jogos

  • Joblackplay  - directx
    avatar

    qual e melhor para começa a desenvolver jogos directx ou unit?
    ou qual engine em e mais amigavel ?

  • ViniGodoy
    avatar

    São coisas completamente diferentes. O DirectX é um pipeline gráfico, bruto, de baixo nível. A Unity é uma engine, cheia de features prontas e focada em facilidade e agilidade.

    Se você quiser fazer uma engine, use DirectX. Se você quer usar uma engine, vá para a Unity.

  • Carlos
    avatar

    Olá Bruno!
    Eu sou iniciante, e gostaria de saber se é difícil fazer o personagem, tem que ser feito em software tipo 3dmax. Eu nunca usei esse tipo de software. Existe algum site que a pessoa consiga esses personagens prontos, ou você recomenda antes de aprender a trabalhar com unit a mexer no 3dmax?

  • Andreas  - re: Respondendo a Pergunta
    avatar

    Carlos!

    Quando iniciamos nossa empresa tambem fizemos essa pergunta para nos mesmo...

    Depois de muito estudo chegamos a uma conclusão!

    Decidimos trabalhar com o Blender!
    Existem muitos tutoriais e videos-aulas expalhados pela rede, o mesmo digo do Unity3D. Começamos com base zero de conhecimento em Blender e quase zero em unity...

    Eu aconselho primeiro da uma estudada no blender para começar a modelar os personagens e cenarios... e depois foca no Unity!O blender é uma ferramenta de alto nivel e free...Ela esta juntinho com os melhores softwares de modelagem pagos como o 3dsMax, Maya, etcccs ! :cheer:

    Essas duas ferramentas juntas são muito poderosas

    Valeu...

    E bom divertimento!

  • Carlos Magno
    avatar

    Olá, vocês tem em mente lançar algum artigo sobre o novo suporte 2d nativo da Unit? Obrigado!

  • Carlos Magno
    avatar

    Olá, vocês tem em mente lançar algum artigo sobre o novo suporte 2d nativo da Unit? Obrigado

  • Carlos Magno
    avatar

    Olá, vocês tem em mente lançar algum artigo sobre o novo suporte 2d nativo da Unit? Obrigado

  • Carlos Magno  - Unit2d
    avatar

    Olá, vocês tem em mente lançar algum artigo sobre o novo suporte 2d nativo da Unit? Obrigado

  • matheus  - personagem
    avatar

    valew agora vou colocar esses javascript no meu personagem

  • Alex Araujo
    avatar

    queria saber como entra em um senario fechado na unity
    e a camera não atraversa a pared ingual no gta

  • alisson  - instant buttons
    avatar

    E ai galera beleza to começando agora no unity 3d e queria saber se alguem pode me ajudar com um probleminha.

    Bom estou tentando criar instant buttons que sao aqueles botoes barulhentos porem nao estou conseguindo criar um script que faça isso
    gostaria de saber se alguem pode me ajudar por favor.

  • alisson  - re: instant buttons
    avatar

    E ai galera beleza to começando agora no unity 3d e queria saber se alguem pode me ajudar com um probleminha.

    Bom estou tentando criar instant buttons que sao aqueles botoes barulhentos porem nao estou conseguindo criar um script que faça isso
    gostaria de saber se alguem pode me ajudar por favor. :confused:

  • Paulo Santos Junior  - Unity no iPad
    avatar

    Olá Bruno! Parabéns pelo tutorial.

    Estou visitando um site (no iPad) e o mesmo tem uma ferramenta desenvolvida no Unity. Porque não abre no ipad???? Na web roda tranquilamente... existe alguma solução para isso???

    valeu!!!

  • matheus  - parabens pela ajuda a nós
    avatar

    obrigado,espero retribuir seus ensinamentos.

Escrever um comentário
Your Contact Details:
Gravatar enabled
Comentário:
[b] [i] [u] [url] [quote] [code] [img]   
:angry::0:confused::cheer:B):evil::silly::dry::lol::kiss::D:pinch::(:shock:
:X:side::):P:unsure::woohoo::huh::whistle:;):S:!::?::idea::arrow:
Security
Por favor coloque o código anti-spam que você lê na imagem.
LAST_UPDATED2  

Busca

Linguagens

Twitter