“Unity3D”索引超出范围异常:数组索引超出范围(尝试在命中时更改精灵)

问题描述 投票:0回答:4

早上好开发人员我知道这个问题之前已经被问过,但我没有在这些答案中找到解决我的问题的方法,首先我想告诉你我只是统一的初学者:p,好在这里是我的问题:我正在构建一个打砖块游戏,我想做的是在砖块被球击中时改变砖块的精灵,为此我正在使用这个脚本:

 public int maxHits;
 public int timesHit;
 private LevelManager levelManager;
 public Sprite[] hitSprites;

 void Start () {
     timesHit = 0;
     levelManager = GameObject.FindObjectOfType<LevelManager> ();
 }

 void OnCollisionEnter2D(Collision2D collision) {
     print ("collison");
     timesHit++;
 }

     // Update is called once per frame
 void Update () {
     if (timesHit >= maxHits) {
         Destroy (gameObject);
     } else {
         LoadSprite ();
     }
     }

 void LoadSprite(){
         int spriteIndex = timesHit - 1;
         this.GetComponent<SpriteRenderer> ().sprite = hitSprites     [spriteIndex];
     }
 }

但我收到此错误:

IndexOutOfRangeException: Array index is out of range. Brick.LoadSprite () (at Assets/Scripts/Brick.cs:34)

而且我每一帧都得到它!,所以它使游戏场景减慢太多,我无法再测试我的游戏。您能告诉我我做错了什么以及如何解决它吗?如果您指导我参加课程以了解更多有关我的错误的信息并且不再这样做,这可能会有所帮助。

c# arrays unity-game-engine
4个回答
0
投票

发生这种情况是因为你的命中时间从 0 开始,然后当你加载精灵时,你会扣除 1,从而得到 -1。然后,在 LoadSprite 的以下行中,您尝试访问索引 -1 (hitSprites[-1]) 处的 hitSprites 数组,这当然超出了范围。

至少,我会添加一些验证来检查索引的范围。


0
投票

您需要限制 spriteIndex 不小于 0(第一个数组索引)并超过 hitSprites.Length 减少 1(最后一个数组索引)。

void LoadSprite(){
         int spriteIndex = Mathf.Clamp(timesHit - 1, 0, hitSprites.Length - 1);
         this.GetComponent<SpriteRenderer> ().sprite = hitSprites [spriteIndex];
     }
 }

提示: 不要在 Update 中调用太多 GetComponent .. 预取所有组件以供以后使用。

private SpriteRenderer _spriteRenderer;

void Awake()
{
_spriteRenderer = GetComponent<SpriteRenderer> ();
}

0
投票

我不知道你在做什么,但你收到了这个错误,因为你正在访问>=

hitSprites
长度的索引。

在使用之前,您应该检查

spriteIndex
变量是否小于
hitSprites
长度。

您的新

LoadSprite
功能应该是:

void LoadSprite()
{
    int spriteIndex = 0;

    //Don't decrement if timesHit  is 0
    if (timesHit > 0)
    {
        spriteIndex = timesHit - 1;
    }
    else
    {
        spriteIndex = timesHit;
    }

    //Return/Exit function if spriteIndex  is equals or more than hitSprites length
    if (spriteIndex > hitSprites.Length - 1)
    {
        return; 
    }
    this.GetComponent<SpriteRenderer>().sprite = hitSprites[spriteIndex];
}

0
投票

@程序员@Dan-Cook @user2867426 首先,我要感谢大家的回答,我从你们身上学到了很多东西,非常感谢! 好吧,我有点错误地修正了我的错误,哈哈。 当我优化代码时,我注意到我在 update() 中使用了这个 if 条件,而我可以直接将它用于 OnCollisionEnter2D():

if (timesHit >= maxHits) {
     Destroy (gameObject);
 } else {
     LoadSprite ();
 }

不知何故解决了我的问题,我不知道如何, 也许问题是它被称为每一帧,但现在不是! 如果你们能向我解释一下如何从 update() 中移动 if 条件解决了问题,我真的很感激 ^^ 再次感谢大家。

© www.soinside.com 2019 - 2024. All rights reserved.