Unity C#ArgumentOutOfRangeException:参数超出范围。参数名称:index

时间:2017-02-14 04:18:24

标签: c# list unity3d

我创造了一个像蛇一样的游戏。在下面的代码中,蛇体的每个片段都是Character类的一个实例。当我尝试添加新角色时,我收到错误:

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>());
    }
}

}

3 个答案:

答案 0 :(得分:4)

更改您的FOR循环条件。从理论上讲,它将超出范围异常。

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--)

答案 1 :(得分:0)

只需将你的循环放入if check

            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");
}

答案 2 :(得分:0)

根据MSDN文档ArgumentOutOfRangeException是:

  

参数值超出时抛出的异常   由调用方法

定义的允许值范围

这意味着,当您尝试根据其索引值访问集合中的项目但实际上该索引不在索引范围内时,会引发异常。大多数案例集合遵循基于0的索引,因此如果您的特定值低于0或者大于集合中元素的数量,则会在访问时导致此异常。

当我们浏览给定的代码段时,我们可以看到您在不同的地方使用了chars [i - 1],显然当i的值为0时,这会导致异常。

简而言之,我们可以说,让chars成为一个集合,并且您正在根据索引访问项目,如果您使用{{1}访问之前的项目,请务必检查chars.Count > 0并且循环限制应该小于i-1

这可能是一个普遍的答案,但希望它能帮助您理解此错误的原因以及如何解决这些错误