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

Erro persiste

O erro persiste de depois que eu faz que o professor fez na aula, vou mandar os erro que estão mostrando no unity: " "SetDestination" can only be called on an active agent that has been placed on a NavMesh. UnityEngine.AI.NavMeshAgent:SetDestination(Vector3) ControlasBoss:Update() (at Assets/Scripts/Gameplay/ControlasBoss.cs:37) "

" NullReferenceException: Object reference not set to an instance of an object GeradorBoss.Update () (at Assets/Scripts/Gameplay/GeradorBoss.cs:26) "

aqui meu código da classes GerardoBoss:

public class GeradorBoss : MonoBehaviour{

    private float tempoProximaGeracao = 0;
    public float tempoEntreGeracoes = 60;
    public GameObject BossPrefab;
    public ReservaFixa reservaBoss;
    private ControlaInterface scriptControlaInteface;
    public Transform[] PosicoesPossiveisGeracao;
    private Transform jogador;

    // Use this for initialization
    private void Start(){
        tempoProximaGeracao = tempoEntreGeracoes;
        scriptControlaInteface = GameObject.FindObjectOfType(typeof(ControlaInterface)) as ControlaInterface;
        jogador = UnityEngine.GameObject.FindWithTag("Jogador").transform;
    }

    // Update is called once per frame
    void Update(){
        if(Time.timeSinceLevelLoad > tempoProximaGeracao){

            if(this.reservaBoss.TemObjeto()){
                Vector3 posicaoCriacao = CalcularPosicaoDistance();
                var boss = this.reservaBoss.PegarObjeto();
                var controleBoss = boss.GetComponent<ControlasBoss>();
                controleBoss.SetPosicao(posicaoCriacao);
                scriptControlaInteface.AvisoChefeInterface();
                tempoProximaGeracao = Time.timeSinceLevelLoad + tempoEntreGeracoes;
            }
        }
    }

    Vector3 CalcularPosicaoDistance (){

        Vector3 posicaoMaiorDistancia = Vector3.zero;

        float maiorDistancia = 0;

        foreach (Transform posicao in PosicoesPossiveisGeracao){

            float distanciaEntreJogador = Vector3.Distance(posicao.position, jogador.position);

            if (distanciaEntreJogador > maiorDistancia){
                maiorDistancia = distanciaEntreJogador;
                posicaoMaiorDistancia = posicao.position;
            }
        }

        return posicaoMaiorDistancia;
    }

}
7 respostas

Aqui o código classe ControlasBoss:

public class ControlasBoss : MonoBehaviour, IMatavel, IReservado{

    private Transform jogador;
    private NavMeshAgent agente;
    private Status statusChefe;
    private AnimacaoPersonagem animacaoBoss;
    private MovimentoPersonagem movimentoBoss;
    public GameObject KitMedicoPrefab;
    public Slider sliderVidaChefe;
    public Image ImagelSlider;
    public Color CorVidaMaxima, CorVidaMinima;
    public GameObject ParticulaSangueZumbi;

    private void Start(){
        jogador = GameObject.FindWithTag("Jogador").transform;
        agente = GetComponent<NavMeshAgent>();
        statusChefe = GetComponent<Status>();
        agente.speed = statusChefe.Velocidade;
        animacaoBoss = GetComponent<AnimacaoPersonagem>();
        movimentoBoss = GetComponent<MovimentoPersonagem>();
        sliderVidaChefe.maxValue = statusChefe.VidaInicial;
        AtualizarInterface();
    }

    public void SetPosicao(Vector3 posicao){
        this.transform.position = posicao;
        this.agente.Warp(posicao);
    }

    private void Update(){
        agente.SetDestination(jogador.position);
        animacaoBoss.Movimentar(agente.velocity.magnitude);

        if(agente.hasPath == true){

            bool estouPertoDoJogador = agente.remainingDistance <= agente.stoppingDistance;

            if(estouPertoDoJogador){

               animacaoBoss.Atacar(true);
               Vector3 direcao = jogador.position - transform.position;
               movimentoBoss.Rotacionar(direcao);

            }else{
               animacaoBoss.Atacar(false);
            }
        }
    }

    void AtacaJogador(){
        int dano = Random.Range(30, 40);
        jogador.GetComponent<ControlaJogador>().TomarDano(dano);
    }

    public void TomarDano(int dano){
        statusChefe.Vida -= dano;
        AtualizarInterface();
        if(statusChefe.Vida <= 0){
            Morrer();
        }
    }

    public void ParticulaSangue(Vector3 posicao, Quaternion rotacao){
        Instantiate(ParticulaSangueZumbi, posicao, rotacao);
    }

    public void Morrer(){
        animacaoBoss.Morrer();
        movimentoBoss.Morrer();
        this.enabled = false;
        agente.enabled = false;
        Instantiate(KitMedicoPrefab, transform.position, Quaternion.identity);
        Destroy(gameObject, 2);
    }

    void AtualizarInterface (){
        sliderVidaChefe.value = statusChefe.Vida;
        float porcentagemVida = (float)statusChefe.Vida / statusChefe.VidaInicial;
        Color corVida = Color.Lerp(CorVidaMinima, CorVidaMaxima, porcentagemVida);
        ImagelSlider.color = corVida;
    }

    public void SetReserva(ReservaFixa reserva){

    }

    public void AoEntrarReserva(){
        this.gameObject.SetActive(false);
    }

    public void AoSairReservar(){
        this.gameObject.SetActive(true);
    }

}

Se você criar um NavMeshAgent e definir sua posição via transform.position = ... e depois tentar SetDestination, ele falhará porque o NavMeshAgent não reconheceu a mudança de posição e não sabe que já está no NavMesh. Use NavMeshAgent.Warp em vez de transform.position para inicializar a posição antes de chamar SetDestination.

Mais o agente já e um variável do NavMeshAgent, porque eu tenho que mudar o

this.agente.Warp(posicao);

para

this.NavMeshAgent.Warp(posicao);

Quando eu mudei para NevMeshAgent aparese um mensagem de erro na unity: Assets/Scripts/Gameplay/ControlasBoss.cs(33,14): error CS1061: Type ControlasBoss' does not contain a definition forNavMeshAgent' and no extension method NavMeshAgent' of typeControlasBoss' could be found. Are you missing an assembly reference?

O que eu tenho que faz para resolver este problema?

Oi Guilherme, tudo bom? vc não precisa mudar para this.NavMeshAgent.Warp(posicao); Usar o atributo "agente" nesse caso funciona.

O que acontece é que para o Warp funcionar o seu Chefão precisa estar em cima na malha de navegação. Ou seja, se a posição em que vc está gerando o chefe não está em cima da malha de navegação vc ainda vai ter um erro.

Outra coisa que vc pode tentar é chamar o Warp antes de mudar a posição do objeto.

Ola eu tirei do metado SetPosicao:

this.agente.Warp(posicaoBoss);

para o Updade, de ter certo.

Mais agora tem outro erro que aparece no terminal no unity 3d:

NullReferenceException: Object reference not set to an instance of an object
ControlasBoss.Start () (at Assets/Scripts/Gameplay/ControlasBoss.cs:28)

O erro Object reference not set to an instance of an object acontece quando você trabalha com alguma variável que não foi instanciada.

No Unity o método Instantiate pode ser usador de duas formas

Instantiate(original: Object);
Instantiate(original: Object, position: Vector3, rotation: Quaternion);

http://docs.unity3d.com/ScriptReference/Object.Instantiate.html

No caso acho que você não instanciou a posicaoBoss

solução!

So conseguir resolver quando eu voltando como esta antes o código ControlaBoss:

 //  public void SetPosicao(Vector3 posicao){
  //     posicaoBoss = this.transform.position = posicao;
  //  }

    private void Update(){
    //    this.agente.Warp(posicaoBoss);
        agente.SetDestination(jogador.position);
        animacaoBoss.Movimentar(agente.velocity.magnitude);

        if(agente.hasPath == true){

            bool estouPertoDoJogador = agente.remainingDistance <= agente.stoppingDistance;

            if(estouPertoDoJogador){

               animacaoBoss.Atacar(true);
               Vector3 direcao = jogador.position - transform.position;
               movimentoBoss.Rotacionar(direcao);

            }else{
               animacaoBoss.Atacar(false);
            }
        }
    }

Class GeradorBoss:

void Update(){
        if(Time.timeSinceLevelLoad > tempoProximaGeracao){

                Vector3 posicaoCriacao = CalcularPosicaoDistance();
                Instantiate(BossPrefab, posicaoCriacao, Quaternion.identity);
                scriptControlaInteface.AvisoChefeInterface();
                tempoProximaGeracao = Time.timeSinceLevelLoad + tempoEntreGeracoes;
        }
    }

Esta do certo sem erro no console unity 3d, e o boss estão seguindo o player.

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