2017-02-14 3 views
-3

Я создаю игру, похожую на змею. В моем коде ниже каждый сегмент тела змеи является экземпляром класса Character. Когда я пытаюсь добавить новый персонаж, я получаю ошибку:Unity C# ArgumentOutOfRangeException: Аргумент за пределами допустимого диапазона. Имя параметра: index

ArgumentOutOfRangeException: Argument is out of range. Parameter name: index 

Других ресурсы онлайн предположили, что есть список, который пуст, что я пытаюсь ссылаться. Но я не вижу никаких доказательств этого случая в моем коде.

Возможно, кто-то умнее меня может найти то, что я сделал неправильно?

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

/* 
* This class controls the entire snake. The snake has a list 
* of segments that are each a character. We can move along the snake 
* by moving the characters bottom up, so that the character replaces 
* the position of the character before him. 
*/ 

public class PlayerController : MonoBehaviour { 

//how many units will he move per 'frame' 
public float moveUnits = 1; 
//how often he will move (every quarter second) 
public float moveTimer = 0.25f; 
private float timeSinceLastMoved; 
public KeyCode dir = KeyCode.RightArrow; 
//locations of boundaries 
public float topBoundary = 4.5f; 
public float bottomBoundary = -4.5f; 
public float leftBoundary = -8.5f; 
public float rightBoundary = 8.5f; 
//Holds all characters for the snake body 
public List<Character> chars = new List<Character>(); 

// Use this for initialization 
void Start() { 
    timeSinceLastMoved = Time.time; 
    getFirstCharacter(); 

} 

// Update is called once per frame 
void Update() { 
    getInput(); 

    if (timeSinceLastMoved + moveTimer < Time.time) { 
     move(); 
     timeSinceLastMoved = Time.time; 
    } 

} 

void getInput() { 

    //if i press right go right, but i can't be going left when i want to go right 
    if (Input.GetKeyDown (KeyCode.RightArrow) && dir != KeyCode.LeftArrow) { 
     dir = KeyCode.RightArrow; 
    } else if (Input.GetKeyDown (KeyCode.LeftArrow) && dir != KeyCode.RightArrow) { 
     dir = KeyCode.LeftArrow; 
    } else if (Input.GetKeyDown (KeyCode.UpArrow) && dir != KeyCode.DownArrow) { 
     dir = KeyCode.UpArrow; 
    } else if (Input.GetKeyDown (KeyCode.DownArrow) && dir != KeyCode.UpArrow) { 
     dir = KeyCode.DownArrow; 
    } 

    //for testing character addition 
    else if (Input.GetKey (KeyCode.A)) { 
     addCharacter(); 
    } 


} 

void move() { 

    float x = 0; 
    float y = 0; 

    if (chars.Count != 0) { 

     //moves the transform in the appropriate directions 
     switch (dir) { 
     case KeyCode.RightArrow: 
      x = transform.position.x + moveUnits; 
      y = transform.position.y; 
      break; 
     case KeyCode.LeftArrow: 
      x = transform.position.x - moveUnits; 
      y = transform.position.y; 
      break; 
     case KeyCode.UpArrow: 
      x = transform.position.x; 
      y = transform.position.y + moveUnits; 
      break; 
     case KeyCode.DownArrow: 
      x = transform.position.x; 
      y = transform.position.y - moveUnits; 
      break; 
     default: 
      break; 
     } 
     //prevents him from moving outside the set boundaries 
     x = Mathf.Clamp (x, leftBoundary, rightBoundary); 
     y = Mathf.Clamp (y, bottomBoundary, topBoundary); 
     Vector2 pos = new Vector2 (x, y); 
     //this moves the whole snake 
     transform.position = pos; 
     //this moves the first snake segment 
     chars[0].transform.position = pos; 

     //for all characters(aka snake segments) 
     //take the position of the segment before you 
     for (int i = chars.Count - 1; i > 0; i++) { 
      chars [i].transform.position = chars [i - 1].transform.position; 
     } 
    } 

} 

void addCharacter() { 
    //the position of the last segment 
    Vector2 prevCharPos = chars[chars.Count-1].transform.position; 
    Vector2 pos; 
    float x = 0; 
    float y = 0; 
    switch (dir) { 
    case KeyCode.RightArrow: 
     x = prevCharPos.x - moveUnits; 
     y = prevCharPos.y; 
     break; 
    case KeyCode.LeftArrow: 
     x = prevCharPos.x + moveUnits; 
     y = prevCharPos.y;; 
     break; 
    case KeyCode.UpArrow: 
     x = prevCharPos.x; 
     y = prevCharPos.y + moveUnits; 
     break; 
    case KeyCode.DownArrow: 
     x = prevCharPos.x; 
     y = prevCharPos.y - moveUnits; 
     break; 
    default: 
     break; 
    } 
    pos = new Vector2 (x, y); 
    //make a new character at the position behind the last segment 
    Character newChar = Instantiate (chars[chars.Count - 1], pos, Quaternion.identity, this.transform); 
    //add him to the list 
    chars.Add (newChar); 
} 

void getFirstCharacter() { 
    //find the character that already exists and add him to the list 
    GameObject firstChar = GameObject.Find ("Character"); 
    if (firstChar != null) { 
     chars.Add(firstChar.GetComponent<Character>()); 
    } 
} 

}

+2

Надеюсь, что это не ваш первый пост, и вы знаете, как задать вопрос. то почему эта много ненужных строк кодов? –

+0

В какой строке вы получаете это исключение? Отладка к этому моменту мне поможет понять причину проблемы! – Adil

+0

Можете ли вы рассказать нам, на какой строке вы получаете сообщение об ошибке? – mindOfAi

ответ

4

Изменение вашего для условия цикла. Теоретически это исключает исключение из диапазона.

for (int i = chars.Count - 1; i > 0; i++) chars [i].transform.position = chars [i - 1].transform.position;

Я считаю, что ваши намерения должны быть

for (int i = chars.Count - 1; i > 0; i--)

0

Просто поместите за петлю внутри, если проверка

  if(chars.Count>0){ 
      //for all characters(aka snake segments) 
        //take the position of the segment before you 
        for (int i = chars.Count - 1; i > 0; i++) { 
         chars [i].transform.position = chars [i - 1].transform.position; 
        } 
      } 
      else{ 
       Debug.Log("Warning:: chars Count is less than 1"); 
} 
0

Согласно MSDN документации ArgumentOutOfRangeException является:

The exception that is thrown when the value of an argument is outside the allowable range of values as defined by the invoked method

Это означает, исключение будет поднимать, когда вы пытались получить доступ элемент из коллекции, основанный на его значении индекса, но на самом деле этот индекс не является t в диапазоне индексов. большинство коллекций случаев следует за индексом 0, поэтому, если ваше конкретное значение ниже 0 или оно больше количества элементов в коллекции, это приведет к этому исключению при доступе.

Когда мы проходим через данный фрагмент код, мы можем видеть, что вы использовали chars [i - 1] в разных местах, очевидно, это вызовет исключение, когда значение i является 0.

Короче говоря, мы можем сказать, что, пусть chars будет сбор и вы обращаетесь элементы на основе индекса, важно проверить chars.Count > 0, если вы обращаетесь к предыдущему элементу с помощью i-1, а также предельный цикл должен быть меньше chars.Count.

Это может быть обобщен ответ, но надеюсь, что это поможет вам понять причину этой ошибки и как их решить