2016-09-18 97 views
0

早上好开发人员我知道这个问题以前曾被问过,但我没有找到解决方案来解决我的问题这些答案,首先我想告诉你,我只是一个团结初学者:嗯,这里是我的问题:我正在构建一个砖头破碎机游戏,我想要做的是改变精灵当它被用球砸砖头,这样做,我使用这个脚本:“Unity3D”索引超出范围例外:数组索引超出范围(尝试更改精灵命中时)

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)

,我得到它的每一帧!小号o它太慢了游戏场景,我无法再测试我的游戏了。你能告诉我我做错了什么以及如何解决它吗?如果你指导我学习更多关于我的错误的课程并且不会再次这样做,这可能会有所帮助。

回答

0

这是因为你的时间命中从0开始,那么当你加载一个精灵时,你会扣除1给你-1。在接下来的LoadSprite行中,您尝试访问索引为-1的hitSprites数组(hitSprites [-1]),这当然超出了范围。

至少,我会添加一些验证来检查您的索引的边界。

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

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

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

提示: 不要叫太多GetComponent在更新..预取所有组件在清醒以后使用。

private SpriteRenderer _spriteRenderer; 

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

@Programmer @丹 - 库克@ user2867426 拳头,我要感谢大家对你的答案,我学到了很多,从你们的话,非常感谢你! 好吧,我有点错误解决了我的错误哈​​哈。 当我优化我的代码我注意到,我在确定使用此条件的更新(),而我可以直接用它来OnCollisionEnter2D():

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

,并在某种程度上是固定我的问题,我不知道如何, 也许问题是,它被称为每一帧,现在不是! 如果你们可以向我解释,如果update()的条件解决了问题,我真的很感激它^^ 再次感谢所有人。

+0

lol接受答案然后取消接受....要回答你的问题,那是因为从'OnCollisionEnter2D'调用它只会在实际存在命中时调用它。但是当你将代码移动到'Update'函数时,无论是否存在命中,每秒或每帧都会被调用60次。快乐的编码! – Programmer

+0

@Programmer aaah好吧我现在明白了,所以发生的事情是,在任何命中之前,timesHit = 0;并且因为spriteIndex = timesHit - 1;然后spriteIndex得到-1,这就是导致问题的原因! 所以解决它的另一种方法是在LoadSprite()方法 的顶部添加“if(timeshit <1)return;”,这将防止spriteIndex获得值-1:D –

+0

是的,这是正确的。您还应该确保长度不超过或等于'hitSprites'的长度。 'hitSprites.Length - 1'。我在我的回答中解释了这一点。 – Programmer