Solucionado (ver solução)
Solucionado
(ver solução)
1
resposta

Resolvido: Problemas com Zumbis (atravessando paredes, tremeliques e fazendo "breakdance" no chão)

Atravessando paredes: Parece que nos métodos MovimentoPersonagem.Morrer e MovimentoPersonagem.Reiniciar o meuRigidbody.isKinematic está sendo ajustado invertido, fazendo com que os zumbis ignorem colisores. https://github.com/alura-cursos/Alura_UnityMobile3/blob/Aula7/Assets/Scripts/Gameplay/MovimentoPersonagem.cs

    public void Morrer ()
    {
        meuRigidbody.constraints = RigidbodyConstraints.None;
        meuRigidbody.velocity = Vector3.zero;
        meuRigidbody.isKinematic = false; //deveria ser true
        GetComponent<Collider>().enabled = false;
    }

    public void Reiniciar()
    {
        meuRigidbody.isKinematic = true; //deveria ser false
        GetComponent<Collider>().enabled = true;
    }

Trocando isso eles param de atravessar obstáculos.

Tremeliques Quando estão vagando e param, pq chegaram no ponto final, os zumbis começam a tremer. Quando o jogo era rodado para computador não era visível, mas no mobile ficou bem aparente. A solução foi só aumentar a tolerância para descobrir se chegou no destino. Creio que o FPS no mobile é menor, aumentando o valor do deltaTime e com isso a tolerância de 0,05 unidades não é suficiente. O zumbi tem velocidade de 5 unidades por segundo, com um 120 FPS no desktop o deltaTime fica em 0,008, o que faz o zumbi andar 0,04 unidades por frame, então a tolerância de 0,05 fica tranquilo. Com um 60 FPS no mobile, o deltaTime fica em 0,016, fazendo o zumbi andar 0,08 unidades por frame, ultrapassando a tolerância de 0,05, e gerando assim os tremeliques. Deixei a tolerância em 0,5, com isso não ocorrerão tremeliques até 10 FPS.

        bool ficouPertoOSuficiente = Vector3.Distance(transform.position, posicaoAleatoria) <= 0.5;

Zumbis fazendo "breakdance" no chão Este problema foi mais complicado de resolver. Debugando os zumbis, pausando o jogo e colocando o inspector em modo debug, vi que a direção do MovimentoPersonagem ficava completamente maluca nesses zumbis que estavam dançando "breakdance" no chão (tremendo e girando deitados). Isso me fez desconfiar do método de normalização, que descobri que, se um vetor é muito pequeno, retorna um vetor zero. Mesmo após normalizar no SetDirecao, forcei para que o Y fosse sempre 0 também. Também em vez de testar se o vetor que será normalizado é zero, estou testando se o sqrMagnitude (evitando raiz quadrada) é maior que 0,05.

    public void SetDirecao(Vector3 direcao)
    {
        if (direcao.sqrMagnitude > 0.05)
        {
            this.Direcao = direcao.normalized;
            this.Direcao = new Vector3(Direcao.x, 0, Direcao.z);
        }
        else
        {
            this.Direcao = Vector3.forward;
        }
    }

    public void Rotacionar (Vector3 direcao)
    {
        if (direcao.sqrMagnitude > 0.05)
        {
            var direcaoNormalizada = direcao.normalized;
            direcaoNormalizada.y = 0;
            Quaternion novaRotacao = Quaternion.LookRotation(direcaoNormalizada);
            meuRigidbody.MoveRotation(novaRotacao);
        }
    }    

Este é o meu projeto final https://github.com/jseling/CursoAlura-UnityMobile-Parte3

Ainda tem um erro no salvar e mostrar o maior tempo na tela de game over que não resolvi.

1 resposta
solução!

Olá Jerson, tudo bem?

Que bom ver que você conseguiu lidar com os problemas dos zumbis no seu jogo! É realmente gratificante quando conseguimos resolver desafios que parecem complicados.

Parabéns pela sua dedicação em depurar o código e encontrar as soluções para esses problemas. Aumentar a tolerância para determinar se o zumbi chegou ao seu destino foi uma excelente ideia. Além disso, a decisão de forçar o valor de Y para 0 no método SetDirecao também foi muito acertada.

Sobre o erro no salvar e mostrar o maior tempo na tela de game over, O problema está ocorrendo porque você está salvando o tempo da pontuação máxima antes de compará-lo com o tempo atual. Isso faz com que o valor salvo seja sempre o antigo. Para corrigir isso, você precisa alterar a ordem das operações no método AjustarPontuacaoMaxima().

Uma possível solução para o método AjustarPontuacaoMaxima() é a seguinte:

void AjustarPontuacaoMaxima (int min, int seg)
{
    if (Time.timeSinceLevelLoad > tempoPontuacaoSalvo)
    {
        tempoPontuacaoSalvo = Time.timeSinceLevelLoad;
        PlayerPrefs.SetFloat("PontuacaoMaxima", tempoPontuacaoSalvo);
    }
    else
    {
        min = (int)tempoPontuacaoSalvo / 60;
        seg = (int)tempoPontuacaoSalvo % 60;
    }

    TextoPontuacaoMaxima.text =
        string.Format("Seu melhor tempo é {0}min e {1}s", min, seg);
}

Deste modo verificamos se o tempo atual é maior do que o tempo salvo. Se for, atualizamos o tempo salvo e salvamos no PlayerPrefs. Caso contrário, usamos o valor do tempo salvo para exibir a pontuação máxima. Isso garante que o tempo mais longo seja sempre exibido corretamente.

Espero ter ajudado, qualquer dúvida, me coloco à disposição! Bons estudos!

Sucesso

Um grande abraço e até mais!

Caso este post tenha lhe ajudado, por favor, marcar como solucionado ✓. Bons Estudos!