Hello I’m having some trouble with calling a function with my code, I am trying to create an endless runner type game so as my player moves I need to create Objects, on awake I instantiate 20 of my prefab and add them them to an List, this List is for the Objects I have not used yet, on start I call my Spawn function 18 times which transforms my Objects to where they need to be and then adds them to another List whilst removing themselves from their current List, this List contains the Objects I have already used and then I grab the first element from the used List and add it to the back of my first List ready to be used again, I am trying to object pool.
The idea of the List’s is for when I spawn a “turn point” I add a prefab to each area of access and each area has it’s own List and I add a Object from that area to the List so when my character turns a corner I have every Object in front of him belonging to a List, depending on the direction my character turns will determine which List I will take an object out of until the List is empty and then a different List will follow and then finally the List for the direction we turned in, this is all to stop removing the Object my character is currently on a way of remembering you could say, this is not complete for turning corners and such at the moment it just creates a straight endless path in front of the character (which is what I want for the moment) but I can’t even get that to work and I have literally done this a few times before I must be losing it, I created a script like this a while back I still have it and it works I just decided to write a new one differently from scratch to see if I could improve it overall.
My problem is that my start function calls Spawn 18 times without fail… works like a charm so I have 18 Objects in front of my character, every time he leaves an Object I want to call Spawn which then adds the Object we just left to the end of the path, I use OnTriggerExit to call Spawn and everytime I call Spawn from anywhere in my player script I get:
“ArgumentOutOfRangeException: Argument is out of range.
Parameter name: index
System.Collections.Generic.List`1[UnityEngine.GameObject].get_Item (Int32 index) (at /Users/builduser/buildslave/mono/build/mcs/class/corlib/System.Collections.Generic/List.cs:633)
GameManager.Spawn () (at Assets/Scripts/GameManager.cs:103)
Player.OnTriggerExit (UnityEngine.Collider other) (at Assets/Scripts/Player.cs:163)”
But if I call Spawn from within it’s own script with some input in Update everything works!
If I call Spawn from the player script with anything it wont work, I made a test function in the manager script with a debug.log and called that from my player script and that works it’s only my Spawn function!
I’m not well experienced i’m still trying to get to grips with everything, I have been learning on & off for about 2-3 years, If some one could help me with this I would be so thankful.!!
My manager Script:
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
public class GameManager : MonoBehaviour {
public Player player;
public GameObject[] Prefabs;
public GameObject currentPrefab1, currentPrefab2, currentPrefab3;
public List <GameObject> forward, left, right, turnPoints;
public int toSpawn = 2, nextSpawn = 1, lastSpawn = 0, randomTP = 0, randomRot = 0, pooledAmount = 20;
public List <int> list = new List <int>();
// bool restarting;
void Awake () {
for (int i = 0; i < pooledAmount; i++) {
GameObject hallSpawn1 = (GameObject)Instantiate (Prefabs [0]);
forward.Add (hallSpawn1);
hallSpawn1.name = ("Hallway " + i);
}
GameObject turnpointSpawn1 = (GameObject)Instantiate (Prefabs [1]);
turnpointSpawn1.SetActive (false);
turnPoints.Add (turnpointSpawn1);
}
void Start () {
forward [0].transform.position = Vector3.zero;
currentPrefab1 = forward [0];
for (int i = 0; i < 19; i++) {
forward [i +1].transform.position = currentPrefab1.transform.GetChild (0).transform.position;
forward [i +1].transform.eulerAngles = currentPrefab1.transform.eulerAngles;
currentPrefab1 = forward [i +1];
}
}
public void Spawn () {
if (list.Any()) {
toSpawn = list [0];
list.Remove (list [0]);
}
switch (toSpawn) {
case 0:
turnPoints [0].transform.position = currentPrefab1.transform.GetChild (0).transform.position;
turnPoints [0].transform.eulerAngles = currentPrefab1.transform.eulerAngles;
player.newPos = turnPoints [0].transform.GetChild (0).position;
currentPrefab1 = turnPoints [randomTP];
currentPrefab2 = turnPoints [randomTP].transform.GetChild (0).gameObject;
currentPrefab3 = turnPoints [randomTP].transform.GetChild (1).gameObject;
turnPoints [randomTP].SetActive (true);
SetRot ();
break;
case 1:
forward [0].transform.position = currentPrefab2.transform.GetChild (0).position;
forward [0].transform.eulerAngles = currentPrefab2.transform.GetChild (0).eulerAngles;
currentPrefab2 = forward [0];
left.Add (forward [0]);
forward.Remove (forward [0]);
break;
case 2:
forward [0].transform.position = currentPrefab1.transform.GetChild (0).transform.position;
forward [0].transform.eulerAngles = currentPrefab1.transform.eulerAngles;
currentPrefab1 = forward [0];
forward.Add (forward [0]);
forward.Remove (forward [0]);
break;
case 3:
forward [0].transform.position = currentPrefab3.transform.GetChild (0).position;
forward [0].transform.eulerAngles = currentPrefab3.transform.GetChild (0).eulerAngles;
currentPrefab3 = forward [0];
right.Add (forward [0]);
forward.Remove (forward [0]);
break;
}
}
void SetRot () {
randomRot = 0;//Random.Range (0, 6);
switch (randomRot) {
case 0:
turnPoints [0].transform.GetChild (4).gameObject.SetActive (true);
turnPoints [0].transform.GetChild (5).gameObject.SetActive (true);
turnPoints [0].transform.GetChild (4).localEulerAngles = new Vector3 (180, 0, 0);
turnPoints [0].transform.GetChild (5).localEulerAngles = new Vector3 (180, 270, 0);
toSpawn = 1;
break;
case 1:
turnPoints [0].transform.GetChild (4).gameObject.SetActive (true);
turnPoints [0].transform.GetChild (5).gameObject.SetActive (true);
turnPoints [0].transform.GetChild (4).localEulerAngles = new Vector3 (180, 180, 0);
turnPoints [0].transform.GetChild (5).localEulerAngles = new Vector3 (180, 270, 0);
toSpawn = 3;
break;
case 2:
turnPoints [0].transform.GetChild (4).gameObject.SetActive (true);
turnPoints [0].transform.GetChild (4).localEulerAngles = new Vector3 (180, 270, 0);
turnPoints [0].transform.GetChild (5).gameObject.SetActive (false);
list = new List <int> {1 ,3, 1, 3, 1, 3, 1, 3, 1, 3, 1 ,3, 1, 3, 1, 3, 1, 3, 1, 3};
break;
case 3:
turnPoints [0].transform.GetChild (4).gameObject.SetActive (true);
turnPoints [0].transform.GetChild (4).localEulerAngles = new Vector3 (180, 0, 0);
turnPoints [0].transform.GetChild (5).gameObject.SetActive (false);
list = new List <int> {1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2};
break;
case 4:
turnPoints [0].transform.GetChild (4).gameObject.SetActive (true);
turnPoints [0].transform.GetChild (4).localEulerAngles = new Vector3 (180, 180, 0);
turnPoints [0].transform.GetChild (5).gameObject.SetActive (false);
list = new List <int> {2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3};
break;
case 5:
turnPoints [0].transform.GetChild (4).gameObject.SetActive (false);
turnPoints [0].transform.GetChild (5).gameObject.SetActive (false);
list = new List <int> {1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1 , 3};
break;
}
}
public void SpawnAll () {
if (player.rotDir == 2) {
do {
if (left.Any ()) {
forward.Add (left [0]);
left.Remove (left [0]);
} else {
for (int i = 0; i < forward.Count; i++) {
Spawn ();
}
forward.InsertRange (0, right);
right.Clear ();
}
} while (right.Any ());
} else if (player.rotDir == 1) {
do {
if (right.Any ()) {
forward.Add (right [0]);
right.Remove (right [0]);
} else {
for (int i = 0; i < forward.Count; i++) {
Spawn ();
}
forward.InsertRange(0, left);
left.Clear ();
}
} while (left.Any ());
} else {
while (left.Any ()) {
forward.Insert (0, left [0]);
left.Remove (left [0]);
Spawn ();
}
while (right.Any ()) {
forward.Insert (0, right [0]);
right.Remove (right [0]);
Spawn ();
}
}
}
}
My player Script:
using System.Collections;
using UnityEngine;
public class Player : MonoBehaviour {
public float runSpeed = 1;
public float dodgeSpeed = 1;
public float jumpStr = 20;
public float gravity = 20;
public float laneNumber = 2;
public float rotSpeed = 90;
public float degTurned, degToTurn, rotDir;
public bool stopMoving, canRot, willRot, isDead, stopRunning, hasJumped;
public GameManager manager;
public Vector3 newLanePos, newPos;
private Vector3 jumpDir = Vector3.zero;
private Animator anim;
private CharacterController controller;
void Start () {
anim = gameObject.GetComponentInChildren<Animator>();
controller = gameObject.GetComponentInChildren<CharacterController>();
}
void Update () {
if ((!isDead) && (!stopRunning)) {
transform.parent.Translate (0, 0, runSpeed);
}
if (Input.GetKeyUp (KeyCode.LeftArrow) && (!stopMoving)) {
if (canRot) {
willRot = true;
canRot = false;
rotDir = 1;
} else if (laneNumber > 1) {
laneNumber -= 1;
stopMoving = true;
StartCoroutine (StopMovement ());
}
}
if (Input.GetKeyUp (KeyCode.RightArrow) && (!stopMoving)) {
if (canRot) {
willRot = true;
canRot = false;
rotDir = 2;
} else if (laneNumber < 3) {
laneNumber += 1;
stopMoving = true;
StartCoroutine (StopMovement ());
}
}
if (degToTurn > degTurned) {
if (rotDir == 1) {
transform.parent.Rotate (0, -rotSpeed * Time.deltaTime, 0);
} else if (rotDir == 2) {
transform.parent.Rotate (0, rotSpeed * Time.deltaTime, 0);
}
degTurned += rotSpeed * Time.deltaTime;
if (degTurned >= 90)
rotClear ();
}
if (stopMoving) {
if (laneNumber == 1) {
newLanePos = new Vector3 (-5, transform.localPosition.y, transform.localPosition.z);
transform.localPosition = Vector3.MoveTowards (transform.localPosition, newLanePos, dodgeSpeed);
} else if (laneNumber == 2) {
newLanePos = new Vector3 (0, transform.localPosition.y, transform.localPosition.z);
transform.localPosition = Vector3.MoveTowards (transform.localPosition, newLanePos, dodgeSpeed);
} else if (laneNumber == 3) {
newLanePos = new Vector3 (5, transform.localPosition.y, transform.localPosition.z);
transform.localPosition = Vector3.MoveTowards (transform.localPosition, newLanePos, dodgeSpeed);
}
}
if (Input.GetKeyUp (KeyCode.DownArrow) && (!stopMoving) && (!hasJumped) && (controller.isGrounded)) {
anim.SetInteger ("animPar", 2);
stopMoving = true;
controller.height = 2;
controller.center = new Vector3 (0, 2, 0);
StartCoroutine (StopMovement ());
} else if (Input.GetKeyUp (KeyCode.UpArrow) && (!stopMoving) && (!hasJumped)) {
anim.SetInteger ("animPar", 1);
stopMoving = true;
jumpDir.y = jumpStr;
StartCoroutine (Jump ());
}
if ((controller.isGrounded) && (hasJumped)) {
hasJumped = false;
stopMoving = false;
anim.SetInteger ("animPar", 0);
}
jumpDir.y -= gravity * Time.deltaTime;
controller.Move (jumpDir * Time.deltaTime);
}
IEnumerator StopMovement() {
yield return new WaitForSeconds (0.5f);
stopMoving = false;
anim.SetInteger ("animPar", 0);
controller.height = 8;
controller.center = new Vector3 (0, 4, 0);
}
IEnumerator Jump () {
yield return new WaitForSeconds (0.5f);
hasJumped = true;
}
void OnTriggerEnter (Collider other) {
if (other.gameObject.CompareTag ("TurnPointDec")) {
canRot = true;
} else if ((other.gameObject.CompareTag ("TurnPointTurn")) && (willRot)) {
stopRunning = true;
stopMoving = true;
degToTurn = 90;
laneNumber = 2;
willRot = false;
if (rotDir == 1) {
manager.currentPrefab1 = manager.currentPrefab2;
} else {
manager.currentPrefab1 = manager.currentPrefab3;
}
}
}
void OnTriggerExit (Collider other) {
if (other.gameObject.CompareTag ("TurnPointDec")) {
canRot = false;
} else if (other.gameObject.CompareTag ("Hallway")) {
manager.Spawn ();
} else if (other.gameObject.CompareTag ("TurnPoint")) {
other.gameObject.SetActive (false);
manager.toSpawn = 2;
manager.SpawnAll ();
rotDir = 0;
}
}
void OnCollisionEnter (Collision other) {
if (other.gameObject.CompareTag ("KillPoint")) {
isDead = true;
anim.SetInteger ("animPar", 3);
}
}
void rotClear () {
degToTurn = 0;
degTurned = 0;
stopRunning = false;
stopMoving = false;
Vector3 roundToNearest90 = transform.eulerAngles;
roundToNearest90.y = Mathf.Round (roundToNearest90.y / 90) * 90;
transform.parent.eulerAngles = roundToNearest90;
transform.parent.position = newPos;
}
}