user11588099
user11588099

Reputation:

Transform child out of bounds

I don't know what's wrong with my code. The first case that is spawned works correctly, but after that a get the error message "Transform child out of bounds". That's because only the first element is being considered. The objects are spawned by the one called "Spawner" and the script "Mandibula" is attached to them.

I tryed to put a loop, but it doesn't work. How could I fix that?

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

public class Alavanca : MonoBehaviour
{
    //Pegar o player pra impedir ele de largar algum item na bancada
    private PlayerController Player;
    //Pegar a mandibula pra poder acionar a contagem dos espaços
    private Mandibula Mandibula;
    //pegar o spawner, pra poder pegar a bancada pelo seu filho
    private GameObject Spawner;

    void Start()
    {
        Player = GameObject.FindWithTag("Player").GetComponent<PlayerController>();
        Spawner = GameObject.FindWithTag("Spawner");
    }

    private void OnTriggerStay(Collider other)
    {
        if (other.tag == "PlayerCollider")
        {
            Player.PodeLargar = false;
        }

        if (Input.GetButtonDown("Jump") && other.tag == "PlayerCollider")
        {
            try
            {
                for (int i = 0; i < Spawner.transform.childCount; i++)
                {
                    Mandibula = Spawner.transform.GetChild(i).GetComponent<Mandibula>();
                     Mandibula.Contar_Espaços();

                }
            }
            catch
            {

                print("Ainda não tem caso");
            }
        }
    }

    private void OnTriggerExit(Collider other)
    {
        if (other.tag == "PlayerCollider")
        {
            Player.PodeLargar = true;
        }
    }
}

[Added from the delted answer]

The method Contar_Espaços is in the script Mandibula:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class Mandibula : MonoBehaviour
{
    //define o número de espaços
    public ValidadorEspaço1[] espaços;

    //variável para acessar o script do gamecontroller
    private GameController gameController;
    private GameObject controller;

    // Start is called before the first frame update
    void Start()
    {
        controller = GameObject.FindGameObjectWithTag("Controller");
        //acessa o script GameContoller
        gameController = controller.GetComponent<GameController>();
    }

    // Update is called once per frame
    public void Contar_Espaços()
    {
        gameController.contadorPontos = 0;
        for (int i = 0; i <= 13; i++)
        {
            if (espaços[i].DenteCerto)
            {
                gameController.contadorPontos++;//se os dentes e grampos são colocados no lugar certo, o contador incrementa
            }
        }

        if (gameController.contadorPontos == 14)
        {
            //se o jogador colocar todos os dentes e grampos nos lugares corretos, ele soma 1 ponto
            gameController.CasosResolvidos++;
            //após somar um ponto, a mandíbula é destruída para que outra seja spawnada no lugar dela
            Destroy(this.gameObject);
        }
    }
}

Upvotes: 1

Views: 1185

Answers (2)

derHugo
derHugo

Reputation: 90580

In a former post we could see that you have a

if (gameController.contadorPontos == 14)
{
    //se o jogador colocar todos os dentes e grampos nos lugares corretos, ele soma 1 ponto
    gameController.CasosResolvidos++;

    //após somar um ponto, a mandíbula é destruída para que outra seja spawnada no lugar dela
    Destroy(this.gameObject);
}

in your Contar_Espaços().

If you think about it: The moment you destroy a child object obviously the childCount from before becomes invalid and so does your iteration variable i since it now can reach an index where no child can be found anymore.


I'ld recommend as alternative to rather give your method a bool as return type like

public bool Contar_Espaços()
{
    gameController.contadorPontos = 0;
    for (int i = 0; i <= 13; i++)
    {
        if (espaços[i].DenteCerto)
        {
            //se os dentes e grampos são colocados no lugar certo, o contador incrementa
            gameController.contadorPontos++;
        }
    }

    if (gameController.contadorPontos == 14)
    {
        //se o jogador colocar todos os dentes e grampos nos lugares corretos, ele soma 1 ponto
        gameController.CasosResolvidos++;

        //após somar um ponto, a mandíbula é destruída para que outra seja spawnada no lugar dela
        return true;
    }

    return false;
}

and now rather collect all elements that return true and destroy them later e.g. using Linq Where:

using System.Lynq;

...

if (Input.GetButtonDown("Jump") && other.tag == "PlayerCollider")
{
    var todestroy = Spawner.GetComponentsInChildren<Mandibula>(true).Where(m => m.Contar_Espaços());
    foreach(var mand in todestroy) 
    {
        Destroy(mand.gameObject);
    }   
}

this is a shorthand for writing

if (Input.GetButtonDown("Jump") && other.tag == "PlayerCollider")
{
    var todestroy = new List<Mandibula>();

    // gets all Mandibula references from this and any child object
    // (add parameter true for also getting currently disabled or inactive ones)
    var mandibulas = Spawner.GetComponentsInChildren<Mandibula>(true);

    foreach(var m in mandibulas)
    {
        if(m.Contar_Espaços()) todestroy.Add(m);
    }

    foreach(var mand in todestroy) 
    {
        Destroy(mand.gameObject);
    }   
}

In general please have in mind that this community (like all other StackExchange communities) is in English so either remove the comments or translate them to English so they are of use for us as well. You should get used to code and comment in English always. It is the global coding language ;)

Upvotes: 1

Anton Mihaylov
Anton Mihaylov

Reputation: 1348

You can try using GetComponentsInChildren

...

if (Input.GetButtonDown("Jump") && other.tag == "PlayerCollider")
{
    var mandibulas = Spawner.GetComponentsInChildren<Mandibula>();
    foreach(Mandibula mand in mandibulas) 
    {
        mand.Contar_Espaços();
    }   
}

...

Upvotes: 0

Related Questions