Search Unity

[SOLVED] Function Call ArguementOutOfRangeException This is killing me!

Discussion in 'Scripting' started by TheRealTeviel, Feb 12, 2018.

  1. TheRealTeviel

    TheRealTeviel

    Joined:
    Dec 29, 2015
    Posts:
    14
    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:

    Code (CSharp):
    1.  
    2. using System.Collections;
    3. using System.Collections.Generic;
    4. using System.Linq;
    5. using UnityEngine;
    6.  
    7. public class GameManager : MonoBehaviour {
    8.  
    9.     public Player player;
    10.  
    11.     public GameObject[] Prefabs;
    12.     public GameObject currentPrefab1, currentPrefab2, currentPrefab3;
    13.     public List <GameObject> forward, left, right, turnPoints;
    14.     public int toSpawn = 2, nextSpawn = 1, lastSpawn = 0, randomTP = 0, randomRot = 0, pooledAmount = 20;
    15.     public List <int> list = new List <int>();
    16. //    bool restarting;
    17.     void Awake () {
    18.         for (int i = 0; i < pooledAmount; i++) {
    19.             GameObject hallSpawn1 = (GameObject)Instantiate (Prefabs [0]);
    20.             forward.Add (hallSpawn1);
    21.             hallSpawn1.name = ("Hallway " + i);
    22.         }
    23.         GameObject turnpointSpawn1 = (GameObject)Instantiate (Prefabs [1]);
    24.         turnpointSpawn1.SetActive (false);
    25.         turnPoints.Add (turnpointSpawn1);
    26.     }
    27.     void Start () {
    28.         forward [0].transform.position = Vector3.zero;
    29.         currentPrefab1 = forward [0];
    30.         for (int i = 0; i < 19; i++) {
    31.             forward [i +1].transform.position = currentPrefab1.transform.GetChild (0).transform.position;
    32.             forward [i +1].transform.eulerAngles = currentPrefab1.transform.eulerAngles;
    33.             currentPrefab1 = forward [i +1];
    34.         }      
    35.     }
    36.     public void Spawn () {
    37.         if (list.Any()) {
    38.             toSpawn = list [0];
    39.             list.Remove (list [0]);
    40.         }
    41.         switch (toSpawn) {
    42.         case 0:
    43.             turnPoints [0].transform.position = currentPrefab1.transform.GetChild (0).transform.position;
    44.             turnPoints [0].transform.eulerAngles = currentPrefab1.transform.eulerAngles;
    45.             player.newPos = turnPoints [0].transform.GetChild (0).position;
    46.             currentPrefab1 = turnPoints [randomTP];
    47.             currentPrefab2 = turnPoints [randomTP].transform.GetChild (0).gameObject;
    48.             currentPrefab3 = turnPoints [randomTP].transform.GetChild (1).gameObject;
    49.             turnPoints [randomTP].SetActive (true);
    50.             SetRot ();
    51.             break;
    52.         case 1:
    53.             forward [0].transform.position = currentPrefab2.transform.GetChild (0).position;
    54.             forward [0].transform.eulerAngles = currentPrefab2.transform.GetChild (0).eulerAngles;
    55.             currentPrefab2 = forward [0];
    56.             left.Add (forward [0]);
    57.             forward.Remove (forward [0]);
    58.             break;
    59.         case 2:
    60.             forward [0].transform.position = currentPrefab1.transform.GetChild (0).transform.position;
    61.             forward [0].transform.eulerAngles = currentPrefab1.transform.eulerAngles;
    62.             currentPrefab1 = forward [0];
    63.             forward.Add (forward [0]);
    64.             forward.Remove (forward [0]);
    65.             break;
    66.         case 3:
    67.             forward [0].transform.position = currentPrefab3.transform.GetChild (0).position;
    68.             forward [0].transform.eulerAngles = currentPrefab3.transform.GetChild (0).eulerAngles;
    69.             currentPrefab3 = forward [0];
    70.             right.Add (forward [0]);
    71.             forward.Remove (forward [0]);
    72.             break;
    73.         }
    74.     }
    75.     void SetRot () {
    76.         randomRot = 0;//Random.Range (0, 6);
    77.         switch (randomRot) {
    78.         case 0:
    79.             turnPoints [0].transform.GetChild (4).gameObject.SetActive (true);
    80.             turnPoints [0].transform.GetChild (5).gameObject.SetActive (true);
    81.             turnPoints [0].transform.GetChild (4).localEulerAngles = new Vector3 (180, 0, 0);
    82.             turnPoints [0].transform.GetChild (5).localEulerAngles = new Vector3 (180, 270, 0);
    83.             toSpawn = 1;
    84.             break;
    85.         case 1:
    86.             turnPoints [0].transform.GetChild (4).gameObject.SetActive (true);
    87.             turnPoints [0].transform.GetChild (5).gameObject.SetActive (true);
    88.             turnPoints [0].transform.GetChild (4).localEulerAngles = new Vector3 (180, 180, 0);
    89.             turnPoints [0].transform.GetChild (5).localEulerAngles = new Vector3 (180, 270, 0);
    90.             toSpawn = 3;
    91.             break;
    92.         case 2:
    93.             turnPoints [0].transform.GetChild (4).gameObject.SetActive (true);
    94.             turnPoints [0].transform.GetChild (4).localEulerAngles = new Vector3 (180, 270, 0);
    95.             turnPoints [0].transform.GetChild (5).gameObject.SetActive (false);
    96.             list = new List <int> {1 ,3, 1, 3, 1, 3, 1, 3, 1, 3, 1 ,3, 1, 3, 1, 3, 1, 3, 1, 3};
    97.             break;
    98.         case 3:
    99.             turnPoints [0].transform.GetChild (4).gameObject.SetActive (true);
    100.             turnPoints [0].transform.GetChild (4).localEulerAngles = new Vector3 (180, 0, 0);
    101.             turnPoints [0].transform.GetChild (5).gameObject.SetActive (false);
    102.             list = new List <int> {1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2};
    103.             break;
    104.         case 4:
    105.             turnPoints [0].transform.GetChild (4).gameObject.SetActive (true);
    106.             turnPoints [0].transform.GetChild (4).localEulerAngles = new Vector3 (180, 180, 0);
    107.             turnPoints [0].transform.GetChild (5).gameObject.SetActive (false);
    108.             list = new List <int> {2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3};
    109.             break;
    110.         case 5:
    111.             turnPoints [0].transform.GetChild (4).gameObject.SetActive (false);
    112.             turnPoints [0].transform.GetChild (5).gameObject.SetActive (false);
    113.             list = new List <int> {1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1 , 3};
    114.             break;
    115.         }
    116.     }
    117.  
    118.     public void SpawnAll () {
    119.         if (player.rotDir == 2) {
    120.             do {
    121.                 if (left.Any ()) {
    122.                     forward.Add (left [0]);
    123.                     left.Remove (left [0]);
    124.                 } else {
    125.                     for (int i = 0; i < forward.Count; i++) {
    126.                         Spawn ();
    127.                     }
    128.                     forward.InsertRange (0, right);
    129.                     right.Clear ();
    130.                 }
    131.             } while (right.Any ());
    132.         } else if (player.rotDir == 1) {
    133.             do {
    134.                 if (right.Any ()) {
    135.                     forward.Add (right [0]);
    136.                     right.Remove (right [0]);
    137.                 } else {
    138.                     for (int i = 0; i < forward.Count; i++) {
    139.                         Spawn ();
    140.                     }
    141.                     forward.InsertRange(0, left);
    142.                     left.Clear ();
    143.                 }
    144.             } while (left.Any ());
    145.         } else {
    146.                 while (left.Any ()) {
    147.                     forward.Insert (0, left [0]);
    148.                     left.Remove (left [0]);
    149.                     Spawn ();
    150.             }
    151.                 while (right.Any ()) {
    152.                     forward.Insert (0, right [0]);
    153.                     right.Remove (right [0]);
    154.                     Spawn ();
    155.             }
    156.         }
    157.     }
    158. }
    159.  
    My player Script:

    Code (CSharp):
    1.  
    2. using System.Collections;
    3. using UnityEngine;
    4.  
    5. public class Player : MonoBehaviour {
    6.     public float runSpeed = 1;
    7.     public float dodgeSpeed = 1;
    8.     public float jumpStr = 20;
    9.     public float gravity = 20;
    10.     public float laneNumber = 2;
    11.     public float rotSpeed = 90;
    12.     public float degTurned, degToTurn, rotDir;
    13.     public bool stopMoving, canRot, willRot, isDead, stopRunning, hasJumped;
    14.     public GameManager manager;
    15.     public Vector3 newLanePos, newPos;
    16.     private Vector3 jumpDir = Vector3.zero;
    17.     private Animator anim;
    18.     private CharacterController controller;
    19.     void Start () {
    20.         anim = gameObject.GetComponentInChildren<Animator>();
    21.         controller = gameObject.GetComponentInChildren<CharacterController>();
    22.     }
    23.     void Update () {
    24.         if ((!isDead) && (!stopRunning)) {
    25.             transform.parent.Translate (0, 0, runSpeed);
    26.         }
    27.         if (Input.GetKeyUp (KeyCode.LeftArrow) && (!stopMoving)) {
    28.             if (canRot) {
    29.                 willRot = true;
    30.                 canRot = false;
    31.                 rotDir = 1;
    32.             } else if (laneNumber > 1) {
    33.                 laneNumber -= 1;
    34.                 stopMoving = true;
    35.                 StartCoroutine (StopMovement ());
    36.             }
    37.         }
    38.         if (Input.GetKeyUp (KeyCode.RightArrow) && (!stopMoving)) {
    39.             if (canRot) {
    40.                 willRot = true;
    41.                 canRot = false;
    42.                 rotDir = 2;
    43.             } else if (laneNumber < 3) {
    44.                 laneNumber += 1;
    45.                 stopMoving = true;
    46.                 StartCoroutine (StopMovement ());
    47.             }
    48.         }
    49.         if (degToTurn > degTurned) {
    50.             if (rotDir == 1) {
    51.                 transform.parent.Rotate (0, -rotSpeed * Time.deltaTime, 0);
    52.             } else if (rotDir == 2) {
    53.                 transform.parent.Rotate (0, rotSpeed * Time.deltaTime, 0);
    54.             }
    55.             degTurned += rotSpeed * Time.deltaTime;
    56.             if (degTurned >= 90)
    57.                 rotClear ();
    58.         }
    59.         if (stopMoving) {
    60.             if (laneNumber == 1) {
    61.                 newLanePos = new Vector3 (-5, transform.localPosition.y, transform.localPosition.z);
    62.                 transform.localPosition = Vector3.MoveTowards (transform.localPosition, newLanePos, dodgeSpeed);
    63.             } else if (laneNumber == 2) {
    64.                 newLanePos = new Vector3 (0, transform.localPosition.y, transform.localPosition.z);
    65.                 transform.localPosition = Vector3.MoveTowards (transform.localPosition, newLanePos, dodgeSpeed);
    66.             } else if (laneNumber == 3) {
    67.                 newLanePos = new Vector3 (5, transform.localPosition.y, transform.localPosition.z);
    68.                 transform.localPosition = Vector3.MoveTowards (transform.localPosition, newLanePos, dodgeSpeed);
    69.             }
    70.         }
    71.         if (Input.GetKeyUp (KeyCode.DownArrow) && (!stopMoving) && (!hasJumped) && (controller.isGrounded)) {
    72.             anim.SetInteger ("animPar", 2);
    73.             stopMoving = true;
    74.             controller.height = 2;
    75.             controller.center = new Vector3 (0, 2, 0);
    76.             StartCoroutine (StopMovement ());
    77.         } else if (Input.GetKeyUp (KeyCode.UpArrow) && (!stopMoving) && (!hasJumped)) {
    78.             anim.SetInteger ("animPar", 1);
    79.             stopMoving = true;
    80.             jumpDir.y = jumpStr;
    81.             StartCoroutine (Jump ());
    82.         }
    83.         if ((controller.isGrounded) && (hasJumped)) {
    84.             hasJumped = false;
    85.             stopMoving = false;
    86.             anim.SetInteger ("animPar", 0);
    87.         }
    88.         jumpDir.y -= gravity * Time.deltaTime;
    89.         controller.Move (jumpDir * Time.deltaTime);
    90.     }
    91.     IEnumerator StopMovement() {
    92.         yield return new WaitForSeconds (0.5f);
    93.         stopMoving = false;
    94.         anim.SetInteger ("animPar", 0);
    95.         controller.height = 8;
    96.         controller.center = new Vector3 (0, 4, 0);
    97.     }
    98.     IEnumerator Jump () {
    99.         yield return new WaitForSeconds (0.5f);
    100.         hasJumped = true;
    101.     }
    102.     void OnTriggerEnter (Collider other) {
    103.         if (other.gameObject.CompareTag ("TurnPointDec")) {
    104.             canRot = true;
    105.         } else if ((other.gameObject.CompareTag ("TurnPointTurn")) && (willRot)) {
    106.             stopRunning = true;
    107.             stopMoving = true;
    108.             degToTurn = 90;
    109.             laneNumber = 2;
    110.             willRot = false;
    111.             if (rotDir == 1) {
    112.                 manager.currentPrefab1 = manager.currentPrefab2;
    113.             } else {
    114.                 manager.currentPrefab1 = manager.currentPrefab3;
    115.             }
    116.         }
    117.     }
    118.     void OnTriggerExit (Collider other) {
    119.  
    120.         if (other.gameObject.CompareTag ("TurnPointDec")) {
    121.             canRot = false;
    122.         } else if (other.gameObject.CompareTag ("Hallway")) {
    123.             manager.Spawn ();
    124.         } else if (other.gameObject.CompareTag ("TurnPoint")) {
    125.             other.gameObject.SetActive (false);
    126.             manager.toSpawn = 2;
    127.             manager.SpawnAll ();
    128.             rotDir = 0;
    129.         }
    130.     }
    131.     void OnCollisionEnter (Collision other) {
    132.  
    133.         if (other.gameObject.CompareTag ("KillPoint")) {
    134.             isDead = true;
    135.             anim.SetInteger ("animPar", 3);
    136.         }
    137.     }
    138.     void rotClear () {
    139.         degToTurn = 0;
    140.         degTurned = 0;
    141.         stopRunning = false;
    142.         stopMoving = false;
    143.         Vector3 roundToNearest90 = transform.eulerAngles;
    144.         roundToNearest90.y = Mathf.Round (roundToNearest90.y / 90) * 90;
    145.         transform.parent.eulerAngles = roundToNearest90;
    146.         transform.parent.position = newPos;
    147.     }
    148. }
    149.  
     
    Last edited: Mar 2, 2018
  2. Joe-Censored

    Joe-Censored

    Joined:
    Mar 26, 2013
    Posts:
    11,847
    In the last line of Start in your manager script, you remove index 0 of toBeUsed. On line 103 you then try to set the transform.postion of toBeUsed[0], even though there is nothing at index 0. That's my best guess at least.

    Before you try to reference an object in a list by index number, you should first be sure that index number exists. I'd add a check before your code at line 103 to check what the length of the toBeUsed list is.

    Also it is really confusing when reading your explanation when you continually are using the term "array" when you sometimes mean "list" and "prefab" when you sometimes mean "GameObject". Arrays and Lists aren't the same thing. A prefab is something you instantiate to create a GameObject. Once the object exists in your scene, even if hidden in an object pool, those aren't prefabs. For example, your character can't have 18 prefabs in front of him. That makes no sense, because a prefab is specifically something not actually in your scene. That's like saying you have a vehicle blueprint in your garage, when you mean you have a car in your garage.
     
    Last edited: Feb 12, 2018
    TheRealTeviel likes this.
  3. TheRealTeviel

    TheRealTeviel

    Joined:
    Dec 29, 2015
    Posts:
    14
    when I run the script everything spawns in and without calling anything I am left with 19 objects in the toBeUsed array and 1 in used array, I have made *sure that something occupies toBeUsed [0], the function calls fine from it's own script every single time i call it but it wont call from my player script.
     
  4. Suddoha

    Suddoha

    Joined:
    Nov 9, 2013
    Posts:
    2,824
    Without taking a closer look at everything that touches the lists, let's assume they're initialized correctly and not messed up anywhere (there're some strange parts in your code though).

    Since you say you everything works until you try to call the Spawn method from the player, you should make sure that you've linked the correct manager, i.e. you've neither linked another instance by accident nor you've linked a prefab of the manager.
    That'd explain the error.

    You can check for multiple instances in the scene using T:GameManager ("T colon TComponent") in the scene's search bar, or use a Debug.Log statement to log the GO's names of the GameManager.

    Or simply click on the linked manager in your player to check where it is attached to.

    If neither of both is the issue, something might mess up the lists, you should debug it in this case.


    The elements in the list will be moved to close the gap, so there'll be another one in place, if count was greater than 1.
    Remove() does not behave like listWithTObject[index] = default(TObject).
     
    TheRealTeviel likes this.
  5. TheRealTeviel

    TheRealTeviel

    Joined:
    Dec 29, 2015
    Posts:
    14
    Thank You Suddoha!! yes I linked something wrong can't say what i did wrong but it's working!! i attempted something similar to resolve the error earlier but to no avail arghhh it's always the little things!! Thank You buddy you just cured one major headache!! =L
     
  6. TheRealTeviel

    TheRealTeviel

    Joined:
    Dec 29, 2015
    Posts:
    14
    Yeahh sorry for the poor explanation, I spent 30 minutes trying to make sure I made some sense =L I'm not used to having to explain my problems I usually find a solution before having to hit the forums, i'll try word it better next time for sure, Thank You for your input buddy, everythings helps! =)
     
  7. TheRealTeviel

    TheRealTeviel

    Joined:
    Dec 29, 2015
    Posts:
    14
    Thank You again but if you don't mind me asking but when you said "(there're some strange parts in your code though)"
    if you got a moment could you point out these "strange parts" so maybe I can work about what I could do to improve on it.
     
  8. Suddoha

    Suddoha

    Joined:
    Nov 9, 2013
    Posts:
    2,824
    You're doing some operations that are very inefficient. Not necessarily noticeable, it's not like they're executed non-stop , but there are other types of collections and/or techniques to achieve this more elegantly.

    Additionally there're quite alot of redundant code parts which could be simplified. Unfortunately I don't have any time today, perhaps I can point out some of these in greater detail tomorrow.
     
    TheRealTeviel likes this.
  9. TheRealTeviel

    TheRealTeviel

    Joined:
    Dec 29, 2015
    Posts:
    14
    That's quite alright =) with what you just told me gives me an idea of what I need to be looking into... hitting some more books that's for sure, time to get everything simple & elegant =) cheers dude!
     
    Suddoha likes this.
  10. methos5k

    methos5k

    Joined:
    Aug 3, 2015
    Posts:
    8,712
    I can see 3 small things off the top of my head that could be changed easily for a little organization.
    1) You can group say lines 45 and 53 (from your post) based on the parts that match, and inside that 'if statement', have your other conditions
    2) with your tag checks:
    a) - you can use 'else if' on the second one.
    b) - use "other.gameObject.CompareTag" instead of "=="
    :)
     
    TheRealTeviel likes this.
  11. TheRealTeviel

    TheRealTeviel

    Joined:
    Dec 29, 2015
    Posts:
    14
    Awesome Cheers Buddy! made all those changes, never thought of grouping the input, much easier on the eye.

    Yeahh I had a feeling there was something more appropriate, "==" is more expensive to use I assume?
     
  12. methos5k

    methos5k

    Joined:
    Aug 3, 2015
    Posts:
    8,712
    Cool, cool. :) I think the grouping is a little easier to read, plus you cut down slightly on having to re-check your values. heh.

    Ya, I mean it's small, just a good habit, I suppose. When you return the tag (as a string) to compare, that's a new string, whereas the compare tag just checks and returns true/false for ya.
     
    TheRealTeviel likes this.
  13. TheRealTeviel

    TheRealTeviel

    Joined:
    Dec 29, 2015
    Posts:
    14
    Definitely easier to read and makes more sense! just going through everything else i'm using to see if I can clear them up too.

    Yeahh that makes sense awesome, i'm going to try do my best to make improvements where ever they can be applied, think I also need to get in the habit of actually reading what I write & deciding whether I actually need it =L Cheers for your help buddy Legendary! =)