Tag: omeuprojeto

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();
        }
    }
}
Tags : , ,

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);
    }
}
Tags : , ,

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#

Tags : , ,

Teclas de atalho no Unity

ou

Tags : , ,

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

Tags : , ,