Reputation:
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
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
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