Solucionado (ver solução)
Solucionado
(ver solução)
8
respostas

Quando o chefe é instanciado aparecem 5 de uma vez

Olá, estou tendo um problema com o jogo, na verdade eu acabei de concluir o curso 4 mas quando testei percebi que estão sendo gerados 5 chefes de uma vez

script GeradorBoss:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class GeradorBoss : MonoBehaviour
{
    private float tempoAteSpawn = 0;
    public float TempoEntreSpawns = 60;
    public GameObject BossPrefab;
    private ControlaInterface scriptControlaInterface;
    public Transform[] PosicoesSpawn;
    private Transform jogador;

    public void Start()
    {
        tempoAteSpawn = TempoEntreSpawns;
        scriptControlaInterface = GameObject.FindObjectOfType(typeof(ControlaInterface)) as ControlaInterface;
        jogador = GameObject.FindWithTag("Player").transform;
    }

    public void FixedUpdate()
    {
        if(Time.timeSinceLevelLoad > tempoAteSpawn)
        {
            Vector3 posicaoSpawn = CalculaPosicaoMaisDistante();
            Instantiate(BossPrefab, posicaoSpawn, Quaternion.identity);
            scriptControlaInterface.ApareceAvisoBoss();
            tempoAteSpawn = Time.timeSinceLevelLoad + TempoEntreSpawns;
        }
    }

    Vector3 CalculaPosicaoMaisDistante()
    {
        Vector3 PosicaoMaisDistante = Vector3.zero;
        float maiorDistancia = 0;
        foreach (Transform posicao in PosicoesSpawn)
        {
            float distanciaDoJogador = Vector3.Distance(posicao.position, jogador.position);
            if(distanciaDoJogador > maiorDistancia)
            {
                maiorDistancia = distanciaDoJogador;
                PosicaoMaisDistante = posicao.position;
            }
        }


        return PosicaoMaisDistante;
    }
}

segue o print do momento do spawn: Insira aqui a descrição dessa imagem para ajudar na acessibilidade

8 respostas

Oi, Calebe, tudo bem?

Pelo que vejo no seu código e na imagem que você compartilhou, parece que o seu problema está relacionado com o método FixedUpdate(). Este método é chamado a cada quadro de física do jogo, o que pode variar dependendo da taxa de quadros por segundo (FPS) do jogo.

Isso significa que se o seu jogo estiver rodando a 60 FPS, o método FixedUpdate() será chamado 60 vezes por segundo. Então, se o tempo entre os spawns for menor que o tempo que leva para processar um quadro de física, vários chefes serão instanciados em um único segundo.

Uma possível solução para o seu problema seria mover o código de spawn do chefe para o método Update(), que é chamado uma vez por quadro de renderização, independentemente da taxa de FPS. Isso garantiria que apenas um chefe seja instanciado por quadro, independentemente de quantos quadros estejam sendo processados por segundo.

Aqui está um exemplo de como o seu código ficaria:

public void Update()
{
    if(Time.timeSinceLevelLoad > tempoAteSpawn)
    {
        Vector3 posicaoSpawn = CalculaPosicaoMaisDistante();
        Instantiate(BossPrefab, posicaoSpawn, Quaternion.identity);
        scriptControlaInterface.ApareceAvisoBoss();
        tempoAteSpawn = Time.timeSinceLevelLoad + TempoEntreSpawns;
    }
}

Espero ter ajudado. Caso tenha dúvidas, não hesite em postar no fórum!

Abraços!

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

O código estava inicialmente com Update() e eu troquei para o fixed pra ver se resolvia, mas vou mudar de novo e ver se funciona

Não funcionou, o código agora está assim:

public class GeradorBoss : MonoBehaviour
{
    private float tempoAteSpawn = 0;
    public float TempoEntreSpawns = 60;
    public GameObject BossPrefab;
    private ControlaInterface scriptControlaInterface;
    public Transform[] PosicoesSpawn;
    private Transform jogador;

    public void Start()
    {
        tempoAteSpawn = TempoEntreSpawns;
        scriptControlaInterface = GameObject.FindObjectOfType(typeof(ControlaInterface)) as ControlaInterface;
        jogador = GameObject.FindWithTag("Player").transform;
    }

    public void Update()
    {
        if(Time.timeSinceLevelLoad > tempoAteSpawn)
        {
            Vector3 posicaoSpawn = CalculaPosicaoMaisDistante();
            Instantiate(BossPrefab, posicaoSpawn, Quaternion.identity);
            scriptControlaInterface.ApareceAvisoBoss();
            tempoAteSpawn = Time.timeSinceLevelLoad + TempoEntreSpawns;
        }
    }

    Vector3 CalculaPosicaoMaisDistante()
    {
        Vector3 PosicaoMaisDistante = Vector3.zero;
        float maiorDistancia = 0;
        foreach (Transform posicao in PosicoesSpawn)
        {
            float distanciaDoJogador = Vector3.Distance(posicao.position, jogador.position);
            if(distanciaDoJogador > maiorDistancia)
            {
                maiorDistancia = distanciaDoJogador;
                PosicaoMaisDistante = posicao.position;
            }
        }


        return PosicaoMaisDistante;
    }
}

Insira aqui a descrição dessa imagem para ajudar na acessibilidade

Ainda tô esperando a resposta pra poder postar o jogo

Oi, Calebe, tudo bem?

Sinto muito pela demora em te dar uma resposta!

Após analisar seu código novamente, identifiquei algumas discrepâncias em relação ao código da aula. Recomendo que, neste caso, tente utilizar o código fornecido durante a aula para evitar erros. No entanto, se você preferir manter suas próprias implementações, é importante ressaltar que ao testar seu código com o projeto da aula, obtive alguns erros que dificultaram a resolução do problema.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class GeradorBoss : MonoBehaviour
{
    private float tempoParaProximaGeracao = 0;
    public float tempoEntreGeracoes = 60;
    public GameObject ChefePrefab;

    private void Start()
    {
        tempoParaProximaGeracao = tempoEntreGeracoes;
    }

    private void Update()
    {
        if (Time.timeSinceLevelLoad > tempoParaProximaGeracao)
        {
            Instantiate(ChefePrefab, transform.position, Quaternion.identity);
            tempoParaProximaGeracao = Time.timeSinceLevelLoad + tempoEntreGeracoes;
        }
    }
}

Para podermos deixar seu jogo pronto o mais rápido possível, peço que compartilhe seu projeto comigo. Você pode disponibilizá-lo no GitHub ou no Google Drive. Se optar pelo Google Drive, sugiro compactar a pasta para torná-la mais leve e lembre-se de liberar o acesso. Ficarei muito feliz em ajudá-lo.

Abraços!

solução!

Oi, Calebe,

Agradeço por compartilhar o seu projeto completo, o mesmo foi essencial para buscar uma solução!

O erro ocorre devido ao seu objeto empty "spaw boss" conter 4 outros objetos responsáveis pela localização do spawn, cada um deles tem o script gerador do boss, ou seja, 5 chefes são gerados aos 60 segundos de jogo. Para resolver isso, basta remover o script que gera chefes nesses outros 4 objetos(PosicaoSpawn01, Posi...02 ... PosicaoSpawn04), como mostrado abaixo:

Dentro da unity na categoria de hierarquia(hierarchy), um retângulo da enfase para 4 sub objetos que estão dentro o empty "spaw boss"

Na sua aba de hierarquia(hierarchy), localize os arquivos, com suas respectivas localizações e apague o script de cada um deles

Dentro da unity, no menu de "inspect" a imagem mostra um retângulo vermelho, localizando para os 3 pontinhos de opções do script "geradorBOSS" e depois no campo para remover o component

Lembrando que é somente dos arquivos que estão dentro do "Spaw Boss".

Ao reparar esse ponto, o seu jogo volta a funcionar como esperado.

Espero ter ajudado, caso tenha dúvidas, conte com o fórum.

Abraços!

Muito obrigado Rodrigo!!

Quer mergulhar em tecnologia e aprendizagem?

Receba a newsletter que o nosso CEO escreve pessoalmente, com insights do mercado de trabalho, ciência e desenvolvimento de software