C# Unity как выбрать только один элемент в массиве и отменить выбор других элементов

#c# #arrays #list #for-loop #unity3d

Вопрос:

У меня есть массив игровых объектов, который я просматриваю, чтобы анимировать материал с задержкой для каждого игрового объекта. Я использую сопрограмму для использования WaitForSeconds и цикла for внутри нее, чтобы добавить задержку для каждого объекта.

В итоге происходит то, что все объекты в массиве выбираются, поэтому анимация происходит со всеми ними, а не только с одним объектом за раз

То, что я ищу, только куб, выбранный в индексе, чтобы изменить цвет и вернуть цвет для предыдущих кубов.

Как я могу этого достичь?

  public GameObject[] laneMat; 
 void Update()
 {
    StartCoroutine(matColor(laneMat, .3f));
 }

 IEnumerator matColor(GameObject[] gameObject, float delay)
 {
 time  = Time.deltaTime;
  for (int i = 0; i < laneMat.Length; i  )
  {
     if (duration > time)
     {
         laneMat[i].GetComponent<Renderer>().material.SetColor("_Color", Color.red);
         
         yield return new WaitForSeconds(delay);
     }
     else if (time > duration amp;amp; time < duration   .3f)
        {
            Renderer render = GetComponent<Renderer>();
            render.material.SetColor("_Color", originalColor);
            yield return null;
        }
    
 }
}
 

Я попытался использовать список и сделать еще один цикл внутри первого цикла, чтобы выбрать предыдущие кубики и удалить их с помощью RemoveAt (), но это немного нервно и не тот эффект, который я ищу

Комментарии:

1. Добро пожаловать в Stack Overflow! Не могли бы вы добавить, что в настоящее время делает этот код и чем он отличается от ожидаемого результата? Это может помочь пользователям попытаться понять вашу проблему. Я не совсем понимаю проблему здесь, но я был бы осторожен с использованием метода обновления сопрограммы: сопрограмма будет запускаться каждый кадр. Рассматривали ли вы возможность включения сопрограммы в метод запуска и сохранения цикла сопрограммы навсегда?

2. Спасибо за комментарий, у меня есть сопрограмма в обновлении, потому что я выполняю анимацию в течение определенного времени, и когда это время закончится, все игровые объекты, выбранные в массиве, вернутся к своему первоначальному цвету.. у меня гораздо больший код, который я не включал, я не хотел вызывать больше путаницы, но, думаю, мне следовало бы это сделать. Я отредактирую сообщение

3. Вы определенно не должны начинать новый Коротуин каждый кадр ! Вы получите сотни одновременно выполняемых процедур ….

Ответ №1:

Вы можете использовать условие для своего цикла здесь

     public GameObject[] laneMat; 
     void Update()
     {
        StartCoroutine(matColor(laneMat, .3f));
     }
    
     IEnumerator matColor(GameObject[] gameObject, float delay)
     {
     time  = Time.deltaTime;
      for (int i = 0; i < laneMat.Length; i  )
      {
         if (duration > time)
         {
if(selected = true) { laneMat[i].GetComponent<Renderer>().material.SetColor("_Color", Color.red); } else { laneMat[i].GetComponent<Renderer>().material.Color = defaultColor; }
             
             yield return new WaitForSeconds(delay);
         }
        
     }
    }
 

Ответ №2:

Я думаю, что вам следует изменить перечислитель, чтобы он находился в функции Запуска, а не в функции обновления. Вызов StartCoroutine из Update означает, что вы запускаете новую сопрограмму каждый кадр, которая не зависит от всех других сопрограмм, которые вы уже запустили.

Если вы переместите вызов в функцию запуска, вы можете использовать задержки везде, где это необходимо, чтобы заставить код ждать. Один из способов вернуть другие игровые объекты — это второй цикл, вложенный в первый цикл. Поскольку у вас будет доступ к индексу измененного игрового объекта, вы можете просто не возвращать этот материал игровых объектов.

С этого момента остается только разместить заявления о возврате доходности везде, где вам нужна задержка.

  public GameObject[] laneMat; 
 void Start()
 {
    StartCoroutine(matColor(.3f));
 }

 IEnumerator matColor(float delay)
 {
    while (true) {
        for (int i = 0; i < laneMat.Length; i  )
        {
            laneMat[i].GetComponent<Renderer>().material.SetColor("_Color", Color.red);
             
            //if you want a delay before reverting the other gameobject materials, it should go here
            
            for (int j = 0; j < laneMat.Length; i  ) {
                if (j != i) { //if the index of the current gameObject is different from the one in the outer loop
                    laneMat[j].GetComponent<Renderer>().material.SetColor("_Color", originalColor);
                    
                    //if you want a delay between reverting each gameobject's material, it should go here
                }
            }       

            yield return new WaitForSeconds(delay);
        }
        
        //if you want a delay before the process starts again, it should go here
    }
}
 

Я не тестировал этот код, но я думаю, что это должно быть хорошей отправной точкой.

Желаю удачи!