【问题标题】:C# IndexOutOfRangeException errorC# IndexOutOfRangeException 错误
【发布时间】:2012-02-15 19:25:59
【问题描述】:

这里有一个轻微的 c# 问题。 我目前正在使用 Unity 编写一个小型平台游戏,并且我有一些检查碰撞等的光线投射。

现在,我开始稍微清理代码,将这些光线投射的结果存储到一个整数数组中,但我得到了 IndexOutOfRangeException。

我多次尝试通读我的代码,但似乎找不到导致问题的原因。如果有人可以帮助我,我会很高兴。

这是我的代码:

using UnityEngine;
using System.Collections;

public class PlayerRayCaster : MonoBehaviour {

    public float playerHeight = 1;
    public enum FeetState {Air, Ground};

    public FeetState playerFeetState = FeetState.Air;
    public int feetHitRays;
    public int behindHitRay;

    //Arrays of rays. value of 1 means that ray hits a target, 0 means that it does not hit.
    public int[] sideRays; // [0-3] = Left side. [4-8] = Right side.
    public int[] depthRays; // [0] = Away from camera. [1] = Towards camera.
    public int[] feetRays;

    public int counter;

    void Start(){
        sideRays = new int[8];
        depthRays = new int[2];
        feetRays = new int[3];

    }
    // Update is called once per frame
    void Update () {
        FeetRays();
        SideRays();
        BehindRay();
    }

    //Rays, which check if the character is bumping into an object, left or right.
    void SideRays(){

        float rayLength = 0.4f;
        counter = 0;

        //Left side rays.
        for(int rayHeight = 0 ; rayHeight>=-4 ; rayHeight-=1 , counter++){
            Debug.Log(sideRays[counter]);
            if(Physics.Raycast(transform.position-new Vector3(0,rayHeight/2,0), new Vector3(-1,0,0),rayLength)){
                sideRays[counter] = 1;
                Debug.DrawRay(transform.position-new Vector3(0,rayHeight/2,0), new Vector3(-rayLength,0,0), Color.green);
            }
            else{
                sideRays[counter] = 0;
                Debug.DrawRay(transform.position-new Vector3(0,rayHeight/2,0), new Vector3(-rayLength,0,0), Color.yellow);
            }
        }

        //Right side rays.
        for(int rayHeight = 0;rayHeight>=-4;rayHeight-=1,counter++){
            if(Physics.Raycast(transform.position-new Vector3(0,rayHeight/2,0), new Vector3(1,0,0),rayLength)){
                sideRays[counter] = 1;
                Debug.DrawRay(transform.position-new Vector3(0,rayHeight/2,0), new Vector3(rayLength,0,0), Color.green);
            }
            else{
                sideRays[counter] = 0;
                Debug.DrawRay(transform.position-new Vector3(0,rayHeight/2,0), new Vector3(rayLength,0,0), Color.yellow);
            }
        }
    }

    //Three rays, which check if the characters feet are on the ground or not.
    void FeetRays(){
        feetHitRays = 0;
        float rayLength = 0.2f;
        //Shoots three rays down from player.
        for(float i=-0.7f;i<=0.7f;i+=0.7f){

            if(Physics.Raycast(transform.position-new Vector3(i/2,0,0), new Vector3(0,-1,0),rayLength)){
                feetHitRays++;
                Debug.DrawRay(transform.position-new Vector3(i/2,0,0), new Vector3(0,-rayLength,0), Color.green);
            }
            else{
                Debug.DrawRay(transform.position-new Vector3(i/2,0,0), new Vector3(0,-rayLength,0), Color.red);
            }
        }

        //Sets the feet state.
        if(feetHitRays==0)
        {
            playerFeetState = PlayerRayCaster.FeetState.Air;
        }
        else{
            playerFeetState = PlayerRayCaster.FeetState.Ground;
        }       
    }
    //Shoots a raycast in z-direction from the character, to check for door access.
    void BehindRay(){

        behindHitRay = 0;
        float rayLength = 2;

        if(Physics.Raycast(transform.position, new Vector3(0,0,1), rayLength)){ //Away from camera
            behindHitRay = 1;
            Debug.DrawRay(transform.position, new Vector3(0,0,rayLength), Color.green);
        }
        if(Physics.Raycast(transform.position, new Vector3(0,0,-1), rayLength)){ // Towards camera.
            behindHitRay = -1;
            Debug.DrawRay(transform.position, new Vector3(0,0,-rayLength), Color.green);
        }
    }
}

这是给我例外的那一行:

sideRays[counter] = 1;

提前致谢。

【问题讨论】:

  • sideRays 正在Start() 中初始化,但我看不到它在哪里运行。有没有可能sideRays 从未初始化?
  • 在抛出异常之前 Debug.Log(sideRays[counter]) 读取了什么?
  • 它在Update中运行,它是一个统一函数,每帧调用一次。 Debug.Log 只显示“0”。

标签: c# unity3d indexoutofboundsexception


【解决方案1】:

我相信这是问题所在:

for(int rayHeight = 0 ; rayHeight>=-4 ; rayHeight-=1 , counter++)

你基本上做了两次,这意味着 10 次迭代,而你的数组是这样初始化的:

sideRays = new int[8];

你可能想要:

// Note the > instead of >=
for (int rayHeight = 0; rayHeight > -4; rayHeight--, counter++)

(顺便说一句,我非常强烈建议您不要使用公共字段,但这是另一回事。)

【讨论】:

  • 公共字段在很多 Unity 代码中使用,因为决定在编辑器中序列化/显示它们。 [SerializeField] 属性未在示例代码中使用,就像它应该使用的那样。
  • 谢谢,这是一个典型的错误。我使用公共字段仅用于调试,我可以在运行游戏时在 Unity 编辑器中看到值。不过感谢您的提醒。
【解决方案2】:

您声明大小为 8 的 sideRays,但快速浏览一下您的循环,计数器可能高达 10。

【讨论】:

    【解决方案3】:

    检查for(int rayHeight = 0;rayHeight&gt;=-4;rayHeight-=1,counter++){ 的界限您最终将在每个循环中访问该数组 5 次,并且您已将数组定义为包含 8 个项目。访问 9 和 10 会抛出异常。

    【讨论】:

      猜你喜欢
      • 2020-03-13
      • 2012-06-11
      • 2012-01-15
      • 2017-01-24
      • 2013-02-16
      • 1970-01-01
      • 2021-05-10
      • 2017-08-09
      • 1970-01-01
      相关资源
      最近更新 更多