I am currently working on a 3d game in unity in C#. I've been following a series of tutorials on youtube (burgzerg arcade) for quite a while now, and i've came across the following error. This error only occurs when i instantiate prefabs to my game scene, opposed to dragging and dropping them into the scene hierarchy. In the tutorial, we work on many things including a targeting script and mob generation. The purpose of the targeting script, is to (when pressing tab), checks to see if there are any mobs (prefabs / game objects) within a certain distance, if they are, it adds them to a list, from which sorts them in order from closest to furthest. When the mob generation script instantiates the prefabs, it instantiates them as a child to the spawn points that i made (spawn point game objects), meaning that when the targeting script searches for the game objects, it doesn't recognize that the mobs are there (because they are childed to the spawn points). So what im asking is how can i make it so that when i press tab, it adds the instantiated children to the list? Here is the code for the mob regen script and targeting script. This is the error i get after i press tab using the instantiated mobs. (ps: when i manually drag the prefabs onto the game scene, opposed to instantiating, it works just the way i want because they aren't instantiated as a child).
This is the error i get when i press tab using the mob regen script:
Parameter name: index System.Collections.Generic.List`1[UnityEngine.Transform].get_Item (Int32 index) (at /Users/builduser/buildslave/mono-runtime-and-classlibs/build/mcs/class/corlib/System.Collections.Generic/List.cs:633) Targetting.TargetEnemy () (at Assets/Scripts/Targetting.cs:64) Targetting.Update () (at Assets/Scripts/Targetting.cs:116) The reason i think i am getting this error is because when the mob gen script generates mobs, it instantiates them as a child to the parent spawn points, so when the targetting script looks for tags with 'enemy', it can't find them ( so it doesn't add them to the list) because the cloned mobs are children to the spawn points. I am trying to find a work around but haven't found anything. Could someone please give me a hand to find a solution to my problem? I've tried things like searching for the children, checking for the child count ect ect. but still can't find a way.
Oh also, the spawn points are just empty game objects that i placed around the map.
Code for targetting.cs:
using UnityEngine; using System.Collections.Generic; using System.Collections; public class Targetting : MonoBehaviour { public List<Transform> targets; public Transform selectedTarget; private Transform myTransform; // Use this for initialization void Start () { targets = new List<Transform> (); selectedTarget = null; myTransform = transform; AddAllEnemies(); } public void AddAllEnemies() { GameObject[] go = GameObject.FindGameObjectsWithTag ("Enemy"); foreach (GameObject enemy in go) { Debug.Log ("Adding enemies to list...."); AddTarget (enemy.transform); } } public void AddTarget(Transform enemy) { Debug.Log ("Added enemy to the list"); targets.Add (enemy); } private void SortTargetByDistance() { targets.Sort (delegate(Transform t1, Transform t2) { return Vector3.Distance (t1.position, myTransform.position).CompareTo(Vector3.Distance(t2.position, myTransform.position)); }); } private void TargetEnemy() { if(selectedTarget == null) { SortTargetByDistance(); selectedTarget = targets[0]; //so the list is empty? well at first it is thats why its null, so it isnt adding them to list? doesn't seem like that, how can you output stuff? is there a comma } else { int index = targets.IndexOf (selectedTarget); if(index < targets.Count - 1) { index++; } else { index = 0; } DeselectTarget(); selectedTarget = targets[index]; } SelectTarget(); } private void SelectTarget() { Transform name = selectedTarget.FindChild ("Name"); if(name == null) { Debug.LogError("Could not find the Name on " + selectedTarget.name); return; } name.GetComponent<TextMesh> ().text = selectedTarget.GetComponent<Mob>().Name; name.GetComponent<MeshRenderer> ().enabled = true; selectedTarget.GetComponent<Mob> ().DisplayHealth(); Messenger.Broadcast<bool> ("show mob vitalbars", true); } private void DeselectTarget() { selectedTarget.FindChild("Name").GetComponent<MeshRenderer>().enabled = false; selectedTarget = null; Messenger.Broadcast<bool> ("show mob vitalbars", false); } // Update is called once per frame void Update () { if(Input.GetKeyDown (KeyCode.Tab)) { TargetEnemy(); } } } Code for mob regen script:
using UnityEngine; using System.Collections; using System.Collections.Generic; public class MobGenerator : MonoBehaviour { public enum State { Idle, Initialize, Setup, SpawnMob } public GameObject[] mobPrefabs; // an array to hold all of the prefabs of mobs we want to spawn public GameObject[] spawnPoints; // an array will hold a reference to all of the spawn points in game public State state; // our local variable that holds our current state void Awake() { state = MobGenerator.State.Initialize; } // USE THIS FOR INITIALIZATION IEnumerator Start() { while(true) { switch(state) { case State.Initialize: Initialize(); break; case State.Setup: Setup(); break; case State.SpawnMob: SpawnMob(); break; } yield return 0; } } // make sure that eeverything is initialized before we go on to the next step private void Initialize() { Debug.Log("*** We are in the initialize function ***"); if (!CheckForMobPrefabs()) return; if (!CheckForSpawnPoints ()) return; state = MobGenerator.State.Setup; } // make sure that everything is setup before we continue private void Setup() { Debug.Log("*** We are in the setup function ***"); state = MobGenerator.State.SpawnMob; } // spawn a mob if we have an open spawn point private void SpawnMob() { Debug.Log ("*** Spawn Mob ***"); GameObject[] gos = AvailableSpawnPoints (); for (int cnt = 0; cnt < gos.Length; cnt++) { GameObject go = Instantiate (mobPrefabs [Random.Range (0, mobPrefabs.Length)], gos [cnt].transform.position, Quaternion.identity) as GameObject; go.transform.parent = gos [cnt].transform; Debug.Log ("there are " + go.transform.childCount.ToString () + " children"); state = MobGenerator.State.Idle; } } // check to see that we have at least one mob prefab to spawn private bool CheckForMobPrefabs() { if (mobPrefabs.Length > 0) return true; else return false; } // check to see if we have at least one spawnpoint to spawn mobs at private bool CheckForSpawnPoints() { if (spawnPoints.Length > 0) return true; else return false; } // generate a list of available spawn points that do not have any mobs childed to it private GameObject[] AvailableSpawnPoints() { List<GameObject> gos = new List<GameObject> (); for(int cnt = 0; cnt < spawnPoints.Length; cnt++) { if(spawnPoints[cnt].transform.childCount == 0) { Debug.Log ("*** Spawn point available ***"); gos.Add (spawnPoints[cnt]); } } return gos.ToArray (); } } So as you can see, I am aware of the problem but I am not sure how to go about fixing the problem. Please let me know how or point me in the right direction.