Единство, использующее сопрограмму как нить? - PullRequest
0 голосов
/ 26 августа 2018

У меня есть функция, отнимающая много времени, например ...

Debug.Log("A");

void Froze_Function() {
  for(int i=0; i<50000; ++i)
    // take some time...

  Debug.Log("B");
}

Debug.Log("C");

Я не хочу, чтобы "Froze_Function" задерживала мою программу объединения, поэтому я хочу, чтобы она запускалась в другом потоке.

У Unity есть сопрограмма, но я не знаю, как правильно сделать эту функцию с сопрограммой.

пожалуйста, не говорите, оптимизируйте мою функцию ...

Ответы [ 2 ]

0 голосов
/ 27 августа 2018

Используете ли вы это просто как пример трудоемкой задачи, или вам действительно нужно ждать установленное время?если вам действительно нужно подождать установленное время, в IENumerator (сопрограмма) будет yield return new WaitForSeconds(n), который будет ждать n секунд. Документы на WaitforSeconds

Многопоточный метод

При этом вы также можете использовать новый поток для этого, в зависимости от того, что вы хотите сделать.При работе с несколькими потоками в единстве имейте в виду, что вы не сможете получить доступ к монобиху из нового потока.такие вещи, как gameObject.transform.position и т. д. не будут доступны.Исключением является Debug.Log, к которому можно получить доступ.используйте сопрограмму, если вы хотите отредактировать gameObject вместо этого.

Сам по себе запуск нового потока довольно легко сделать, вот почему вы можете использовать Thread.Sleep, если хотите дождатьсяустановите время, не теряя ни одного исполнения, которое вы все равно потеряете на сопрограмме:

using System.Threading;
public class ThreadStarter
{
   Start()
   {
      Debug.Log("a");
      Thread newThread = new Thread(() => FunctionRunningOnThread());//this function will now execute on the new thread
      newThread.Start();
      Debug.Log("c");
   }

   private void FunctionRunningOnThread()
   {
       Thread.Sleep(5000)//Thread.Sleep is in milliseconds, so this waits 5 seconds
       Debug.Log("B"); //debug.log 
   }
}

- через 5 секунд будет напечатано «ac», а затем «b».Имейте в виду, что работать безопасно с несколькими потоками сложнее, чем работать с одним потоком, так как вам придется иметь дело с условиями гонки, блокируя переменные, чтобы не пытаться редактировать их из нескольких мест вв то же время и намного больше вещей.Это не рекомендуется, если вы не знаете, что делаете, и использование сопрограмм является более безопасным вариантом.

Запуск сопрограммы Функция сопрограммы всегда должна иметь тип IENumerator ивызывается с помощью функции StartCoroutine и всегда возвращает значение, используя yield return это значение может быть null

Start()
{
    Debug.Log("a");
    StartCoroutine(SomeFunction());
    Debug.Log("c";
}

private IENumerator SomeFunction()
{
   yield return new WaitForSeconds(5);//this will wait 5 seconds
   Debug.Log("b");

   //Alternatively you can use this if you want to wait a set of frames
   for(int i = 0; i < 50000; i++)//this will wait 50000 frames
   {
       i++
       yield return new WaitForEndOfFrame();/
   }
}

Это также выведет «a», «c» и затем «b» после 5секунд.Преимущество этого в том, что вы все еще можете редактировать GameObjects внутри сопрограммы, и вам не нужно беспокоиться о безопасности потоков.

0 голосов
/ 26 августа 2018
void Start()
{
    Debug.Log("A");
    StartCoroutine(Froze_Function());
    Debug.Log("C");
}

//Inside a method (class should be MonoBehavour) call: StartCoroutine(Froze_Function()); 

IEnumerator Froze_Function()
{
    float dist;
    for (int i = 0; i < 500; ++i)
    {
        dist = Vector3.Distance(Vector3.up, Vector3.left);
        yield return 0;
    }

        Debug.Log("B");
    yield return 0;
}
...