Category: omeuprojeto
Parte4 – o meu projeto (aprender)
O terreno, coisas interessantes:
shift anula o elemento do terreno;
manipular o brush size e opacity
instalar o package Terrain tools, através do package manager (ativar no project settings, a hipótese de enable preview packages)e surgem outras opções com o package
teclas de atalho com o uso dos brushes: LINK
outras opções, o path finder: LINK
outras opções, o Terrain Tools Sample Asset Pack (free): LINK
depois de instalar é só importar.. neste caso fiz importar tudo. Surge então a hipótese de usar o paint texture e olhar para a secção das layers
Bump Map (informação 3d da imagem, uma layer a partir de mapa 2d, “light catches a shape”)
Height Map (fazer uso do preto/branco para criar informação acerca da altura dos elementos na imagem)
Normal Map (faz uso dos valores de RGB para indicar a direção da luz em termos de x,y e z de cada pixel)
assim sempre que for necessário aplicar uma layer shape é necessário tratar destas três questões:
standart assets para o Unity: LINK
(filtrar… por environment)
Timeline e a Animation
o processo é o mesmo que em Flash ou noutras ferramentas, trabalhar com keyframes e construir e aplicar movimentos entre esses espaços
Parte3 – o meu projeto (aprender)
Alguns dos temas que devem ser debatidos quando se desenvolve um videojogo:
a experiencia do jogador (precisão, e habilidade) (player experience (precision. skillful);
mecânica principal: pilotar habilmente uma nave espacial e evitar o meio ambiente (core mechanic: skilfully fly spaceship and avoid environmental hazards);
loop principal do jogo: ir de a até b para completar o nível e depois avançar para o próximo nível (core game loop: get from a to b to complete the level then progress to the next level).
Outro assunto é o fluxo do jogo e os ecrãs (game flow and screens) e que se resume ao seguinte cenário:
O tema do jogo (estória de elementos gráficos):
uma geração experimental de uma nave espacial;
tentar escapar de um planeta desconhecido.
(qual o tema central do jogo, o nome do jogo,…)
Questões que normalmente surgem quando se desenvolve um videojogo:
quais são os features (características) que eu devo incluir no meu videojogo?
quando é que se deve começar o desenvolvimento?
quais são as prioridades?
e se eu não tiver tempo?
quando é que eu devo parar?
Metodologia Onion Design (core feature ou mecânicas):
Devem haver respostas para:
qual é característica que é única e mais importante para o jogo?
qual é a característica seguinte mais importante?
qual é a característica seguinte mais importante?
(exemplos: movimento do jogador, colisão com o ambiente (e morrer por causa disso), power ups, ir de a para b e começar um novo nível (level progression), existirem obstáculos que se mexem, existência de pontuação, existência de inimigos, fuel..)
Um alternativa a este modelo será a de começar pelo mais difícil e mais complicado primeiro.
coisas interessantes:
A classe MonoBehaviour:
input +infos: LINK
Input.getKey +infos: LINK
simular o vento no jogo, alterar a física do projeto em X por exemplo
o áudio:
deve estar na camara, porque é o local onde o jogador está
para trabalhar o áudio vai ser necessário:
audio listener (na camara)
audio source (o elemento gráfico que tem/produz o áudio)
audio file
problemas com o áudio:
ou quando se faz o play no Unity estar muted
ou no projeto do ficheiro, ir às preferences…
O AudioSource +infos: LINK
O AudioSource PlayOneShot +infos: LINK
As cenas tem que ser geridas e referidas:
O SceneManager + infos: LINK
Pode também existir a necessidade de colocar uma pausa entre o morrer e o renascer, para isso existe o método Invoke()
Tem como referência o uso de uma String e pode ser lento.. alternativa é usar o Coroutine
O Invoke +infos: LINK
Ainda acerca dos prefabs:
convém que sejam feitos como deve ser e não duplicar/acrescentar simplesmente na barra inicial
remover os box colider de todos e aplicar apenas ao elemento pai do prefab
adicionar depois um box colider e moldar de seguida esse box colider com a ferramenta de edit colider
Particle System:
tem um emissor
e tem as partículas
é adicionado como game object ou através de um componente
um particle system tem módulos que permitem controlar o comportamento
se ficar a pink (cor de rosa) ir ao módulo render->material (é porque não tem ainda material)
na secção shape do módulo podemos alterar o comportamento do cone no radius
e manter os loops ativos
Lighting tab:
(menu window-> rendering-> lighting)
permite manipular os elementos relativos ao lighting
existem:
main directional light (sol)
environment lighting ()
scene lights (do tipo spot lights…)
Lighting +infos: LINK
transformações:
através do código
vector3
starting position (x,y,z)
movement vector (x,y,z)
movement factor (efeito de ping pong), entre 0 e 1
Transform +infos: LINK
movimento constante:
Matemátia, Mathf.Sin +infos: LINK
algum código:
using System; using UnityEngine; using UnityEngine.SceneManagement; public class Colisoes : MonoBehaviour { [SerializeField] float tempoLoadNivel = 2.0f; //audio [SerializeField] AudioClip suscesso; [SerializeField] AudioClip insucesso; AudioSource fonteAudio; [SerializeField] ParticleSystem suscessoParticulas; [SerializeField] ParticleSystem insucessoParticulas; bool estadoEmTransicao = false; //lidar com sons, movimentos.. //cheat code bool desligarColisoes = false; void Start() { fonteAudio = GetComponent<AudioSource>(); fonteAudio.Stop(); } void Update() { ResponderATeclasDeDebug(); } void ResponderATeclasDeDebug(){ if(Input.GetKeyDown(KeyCode.L)){ loadOProximoNivel(); }else if(Input.GetKeyDown(KeyCode.C)){ desligarColisoes = !desligarColisoes; } } void OnCollisionEnter(Collision other) { if(estadoEmTransicao == true || desligarColisoes == true) { return; } switch(other.gameObject.tag) { case "Amigo": Debug.Log("Amigo"); break; case "Fuel": Debug.Log("Fuel"); break; case "Finish": Debug.Log("Parabens terminaste"); //loadOProximoNivel(); ComecarSequenciaSucesso(); break; default: //Debug.Log("huns.."); //ou reLoadNivel(); //ou com pausa //ou Invoke("reLoadNivel", 1f); //ou Invoke("ComecaSequenciaCrash", 1f); //criar efeito de pausa com disable teclado ComecaSequenciaCrash(); break; } } void ComecarSequenciaSucesso() { estadoEmTransicao = true; //audio fonteAudio.Stop(); fonteAudio.PlayOneShot(suscesso); //particulas //ParticleSystem.Play(); suscessoParticulas.Play(); //parar o movimento GetComponent<Movimento>().enabled = true; //invoke.. Invoke("loadOProximoNivel", tempoLoadNivel); } void ComecaSequenciaCrash() { estadoEmTransicao = true; //som fonteAudio.Stop(); fonteAudio.PlayOneShot(insucesso); //particulas //ParticleSystem.Play()... insucessoParticulas.Play(); //criar efeito de pausa com disable teclado GetComponent<Movimento>().enabled = false; Invoke("reLoadNivel", 1f); } void loadOProximoNivel() { int cenaCorrenteIndex = SceneManager.GetActiveScene().buildIndex; int proximaCenaIndex = cenaCorrenteIndex + 1; if(proximaCenaIndex == SceneManager.sceneCountInBuildSettings){ proximaCenaIndex = 0; } SceneManager.LoadScene(proximaCenaIndex); } void reLoadNivel() { //ou SceneManager.LoadScene(0); // é a primeira ou com o nome //ou SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex); //voltamos ao inicio //ou int cenaCorrenteIndex = SceneManager.GetActiveScene().buildIndex; SceneManager.LoadScene(cenaCorrenteIndex); } }
using System.Collections; using System.Collections.Generic; using UnityEngine; public class Movimento : MonoBehaviour //herança : MonoBehaviour { Rigidbody rb; [SerializeField] float forcaDoTrust = 100.0f; [SerializeField] float rotacaoDoTrust = 1.0f; //audio AudioSource ruidoMotor; [SerializeField] AudioClip motorFogetao; //sistema de particulas do motor [SerializeField] ParticleSystem motorFogetaoParticulas; [SerializeField] ParticleSystem motorEsquerdaFogetaoParticulas; [SerializeField] ParticleSystem motorDireitaFogetaoParticulas; void Start() { rb = GetComponent<Rigidbody>(); //audio ruidoMotor = GetComponent<AudioSource>(); ruidoMotor.Stop(); motorFogetaoParticulas.Stop(); } void Update() { InteratividadeThrust(); InteratividadeRotacao(); } void InteratividadeThrust() { //getKeyDown: só para saber se ele primiu a tecla //ou (Input.GetKey("up")) ou (Input.GetKey(KeyCode.UpArrow)) //duas escolhas, diferentes signatures if(Input.GetKey(KeyCode.Space)) { InicioThrust(); } else { PararThrust(); } } void InicioThrust() { Debug.Log("Foi pressionado a tecla de SPACE"); //rb.AddRelativeForce(0,1,0); //Vector3 são 3 valores:xyz //Vector3 permite aceder à direcção e velocidade rb.AddRelativeForce(Vector3.up * forcaDoTrust * Time.deltaTime); //equivalente a rb.AddRelativeForce(0,1,0); //audio if (!ruidoMotor.isPlaying) { //ruidoMotor.Play(); //só para um som ruidoMotor.PlayOneShot(motorFogetao); } //particulas if (!motorFogetaoParticulas.isPlaying) { motorFogetaoParticulas.Play(); } } void PararThrust() { ruidoMotor.Stop(); motorFogetaoParticulas.Stop(); } void InteratividadeRotacao() { if(Input.GetKey(KeyCode.A)) { RotacaoEsquerda(); } else if(Input.GetKey(KeyCode.D)) { RotacaoDireita(); } else { PararRotacao(); } } void RotacaoEsquerda() { Debug.Log("Foi pressionado a tecla de A"); RotacaoMetodo(rotacaoDoTrust); //xyz: 0,0,1 if (!motorDireitaFogetaoParticulas.isPlaying) { motorDireitaFogetaoParticulas.Play(); } } void RotacaoDireita() { Debug.Log("Foi pressionado a tecla de D"); //transform.Rotate(-Vector3.forward * rotacaoDoTrust * Time.deltaTime); //xyz: 0,0,1 //ou transform.Rotate(Vector3.back * rotacaoDoTrust * Time.deltaTime); //xyz: 1,0,0 if (!motorEsquerdaFogetaoParticulas.isPlaying) { motorEsquerdaFogetaoParticulas.Play(); } RotacaoMetodo(-rotacaoDoTrust); } private void PararRotacao() { motorDireitaFogetaoParticulas.Stop(); motorEsquerdaFogetaoParticulas.Stop(); } void RotacaoMetodo(float rotacaoDesteFrame) { //freezar o sistema de rotação não deixar o sistema de fisica tomar posse rb.freezeRotation = true; //para rodar manualmente transform.Rotate(Vector3.forward * rotacaoDesteFrame * Time.deltaTime); rb.freezeRotation = false; // unfreezar para que o sistema de fisica tome conta das ações } }
using System.Collections; using System.Collections.Generic; using UnityEngine; public class oscilador : MonoBehaviour { Vector3 posicaoDeInicio; [SerializeField] Vector3 vectorDeMovimento; //slider [SerializeField] [Range(0,1)] float vectorDeFactor; //periodo de tempo [SerializeField] float periodo = 2f; void Start() { //posição inciial posicaoDeInicio = transform.position; Debug.Log(posicaoDeInicio); } // Update is called once per frame void Update() { //para medir o tempo.. /* if(periodo == 0f){ //protecção return; } */ //por ser float a comparação com == pode comprometer. if(periodo <= Mathf.Epsilon){ //protecção return; } float ciclos = Time.time / periodo; //vai crescendo com o tempo //usar Tau, o tal Pi que não é pi e tem em conta o raio const float tau = Mathf.PI * 2; // o valor constante de 6.283 float rawSenoOnda = Mathf.Sin(ciclos * tau); //andar entre -1 e 1 Debug.Log(rawSenoOnda); vectorDeFactor = (rawSenoOnda + 1f) / 2f; //calculo que vai de 0 a 1 Vector3 offset = vectorDeMovimento * vectorDeFactor; transform.position = posicaoDeInicio + offset; } }
using System.Collections; using System.Collections.Generic; using UnityEngine; public class QuitJogo : MonoBehaviour { void Update() { if(Input.GetKeyDown(KeyCode.Escape)) { Debug.Log("Terminou o jogo!!!"); Application.Quit(); } } }
Parte2 – o meu projeto (aprender)
o GameDesign deste projeto:
a experiência do jogador ( player experience ) : agilidade
a mecânica do jogo ( core mechanic ) : movimentos, e de evitar obstáculos
o modo continuo do jogo ( game loop ): ir de a para b
coisas interessantes:
a função Time.deltaTime
usar o cinemachine (para termos acesso a diferentes camaras) +infos: LINK
box colider (lidar com as colisões)
rigidbody (vai permitir trabalhar as colisões, lidar com problemas de rotação, através de congelar (freeze nos constrains)
cores +infos: LINK
GameObject.GetComponent + infos: LINK
Time.time +infos: LINK
Tags +infos: LINK
Transform +infos: LINK
algum código:
using System.Collections; using System.Collections.Generic; using UnityEngine; public class ColisaoMuros : MonoBehaviour { private void OnCollisionEnter(Collision other) { //Debug.Log("colisao com um muro"); //Collision, tipo de variavel //other, quem colidiu comigo //OnCollisionEnter, quando "entra" na colisão //se colidirem contigo muda de cor //GetComponent<MeshRenderer>().material.color = Color.grey; //2) a colisão só deve acontecer se for com o objecto do jogador if(other.gameObject.tag == "Player"){ GetComponent<MeshRenderer>().material.color = Color.grey; //mudar a tag gameObject.tag = "colisao"; } } }
using System.Collections; using System.Collections.Generic; using UnityEngine; public class Mover : MonoBehaviour { //para ficar disponivel no inspctor usamos o [SerializeField] //[SerializeField] float andaX = 0.0f; //[SerializeField] float andaY = 0.01f; //[SerializeField] float andaZ = 0.0f; // Start is called before the first frame update float andaY = 0.0f; [SerializeField]float movimentoVelocidade = 6.0f; void Start() { Debug.Log("parte 2 - inicio do jogo"); ImprimirInstrucoes(); //para mover } // Update is called once per frame void Update() { MoverOJogador(); } void ImprimirInstrucoes(){ Debug.Log("Bem vindo ao jogo"); Debug.Log("Move o jogador com as setas ou WSAD"); Debug.Log("Não vás contras os muros.."); } void MoverOJogador(){ float andaX = Input.GetAxis("Horizontal")*Time.deltaTime*movimentoVelocidade; float andaZ = Input.GetAxis("Vertical")*Time.deltaTime*movimentoVelocidade; transform.Translate(andaX, andaY, andaZ); } }
using System.Collections; using System.Collections.Generic; using UnityEngine; public class Pontuacao : MonoBehaviour { int pontuacao = 0; private void OnCollisionEnter(Collision other) { if(other.gameObject.tag != "colisao"){ pontuacao=pontuacao+1; Debug.Log("pontos: "+pontuacao); } } }
using System.Collections; using System.Collections.Generic; using UnityEngine; public class Queda : MonoBehaviour { [SerializeField] float TempoACorrer = 3.0f; MeshRenderer rendererizacao; Rigidbody corpoDoMuro; void Start() { //esconder a mesh do objeto //GetComponent<MeshRenderer>().enabled = false; rendererizacao = GetComponent<MeshRenderer>(); rendererizacao.enabled = false; corpoDoMuro = GetComponent<Rigidbody>(); corpoDoMuro.useGravity = false; } void Update() { //Time.time, o tempo que passou desde o inicio de play no jogo //Debug.Log(Time.time); if(Time.time > TempoACorrer){ //Debug.Log("ja passaram 3 segundos"); rendererizacao.enabled = true; corpoDoMuro.useGravity = true; } } }
using System.Collections; using System.Collections.Generic; using UnityEngine; public class Roda : MonoBehaviour { [SerializeField] float rodaX = 0.0f; [SerializeField] float rodaY = 0.50f; [SerializeField] float rodaZ = 0.0f; // Update is called once per frame void Update() { transform.Rotate(rodaX,rodaY,rodaZ); } }
Parte1 – o meu projeto (aprender)
coisas interessantes:
tecla F para centrar no objeto que queremos,
realizar um reset nas propriedades com o lado direito do rato no inspetor,
alt+botão esquerdo do rato, selecionado o objeto podemos mover em torno dele
coisas usadas e instaladas:
visual studio code
no VSC instalar o Unity Code Snippets
no VSC instalar o C#
Instalação do Unity
Provavelmente por já ter tido uma instalação de uma versão do Unity, e que foi apenas removida pelo uso do Add/Remove programs em ambiente windows, tive problemas em voltar a instalar.
Surgia sempre o erro de “Installation Aborted” instalação ficava a meio caminho.
A solução foi instalar a interface (hub) de instalação do Unity mais antigo deste local (LINK) e de seguida fui instalar o hub da versão mais recente e funcionou!
Vou usar a versão do Unity 2020.2.4f1, parece que é a mais recente e é uma versão final..
+infos(sobre o erro): LINK