2016-09-18 13 views
0

Доброе утро Разработчики Я знаю, что этот вопрос задан раньше, но я не нашел решения своей проблемы в эти ответы, сначала я хотел бы сказать вам, что я всего лишь новичок в единстве: p, ну вот моя проблема: я строю игру из кирпичного выключателя, что я пытаюсь сделать, - это изменить спрайт кирпич, когда он получает удар по мячу, чтобы сделать это, я использую этот скрипт:«Unity3D» Index Out Of Range Exception: Индекс массива выходит за пределы допустимого диапазона (пытается сменить спрайт при попадании)

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)

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

ответ

0

Это происходит потому, что ваше время удара начинается с 0, затем, когда вы загружаете спрайт, вы вычитаете 1, давая вам -1. В следующей строке LoadSprite вы затем пытаетесь получить доступ к вашему массиву hitSprites по индексу -1 (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]; 
    } 
} 

Совет: Dont назвать слишком много GetComponent в Update .. Prefetch все компоненты в просыпаются для последующего использования.

private SpriteRenderer _spriteRenderer; 

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

@Programmer @ Дан-Кук @ user2867426 кулак, я хотел бы поблагодарить всех вас за ваши ответы, я так много узнал от вас, ребята, так, большое спасибо !! хорошо я kinda по ошибке исправлен мой ошибка lol. , когда я был оптимизации моего кода я заметил, что я использовал это, если условие в обновлении() в то время как я мог бы использовать его непосредственно OnCollisionEnter2D():

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

и каким-то образом, что фиксированная моя проблема я не знаю как, , возможно, проблема заключалась в том, что он назывался каждый отдельный кадр, а теперь это не так! , если вы, ребята, могли бы объяснить мне, как двигаться, если условие от update() исправлено проблема, я действительно ценю это ^^ спасибо всем вам снова.

+0

lol принимает ответ, а затем не принимает его ... Чтобы ответить на ваш вопрос, это потому, что вызов его из 'OnCollisionEnter2D' будет вызываться только тогда, когда на самом деле есть хит. Но когда вы переводите код в функцию «Update», его вызывают 60 раз в секунду или каждый кадр независимо от того, есть ли у него удар или нет. Счастливое кодирование! – Programmer

+0

@ Программист aaah ok я понимаю лучше сейчас, поэтому произошло то, что до того, как были сделаны какие-то хиты, время было = 0; и поскольку spriteIndex = timesHit - 1; то spriteIndex получал -1, и это то, что вызывало проблему !! , так что еще один способ исправить это, добавив «if (timeshit <1) return;» в начало метода LoadSprite() это предотвратит получение spriteIndex значения -1: D –

+0

Да, это правильно. Вы также должны убедиться, что длина не больше или равна длине 'hitSprites'. 'hitSprites.Length - 1'. Я объяснил это в своем ответе. – Programmer