【问题标题】:Is there any way or need to use threads with Unity3d?有什么方法或需要在 Unity3d 中使用线程?
【发布时间】:2016-06-11 11:55:58
【问题描述】:

我有一种巨大的误解 - 如何在单独的线程中计算繁重的东西,获取结果,以及“继续主程序”。 我正在开发棋盘游戏,“棋盘检查”和“AI 思考”的任务需要 cpu,所以我正在尝试将计算分离到另一个线程。

我不是 .NET 程序员,主要是 c++,过去 4 天我读了很多关于 c sharp 和 unity3d 中的协程和线程的内容,但现在我脑子里一团糟,完全失去了任何一种“什么去做”。

我发现,unity 仍然使用 .NET2,所以不能使用 TPL 或 TPLv3。 我正在寻找 Foundation Tasks 库(https://github.com/NVentimiglia/Unity3d-Foundation/wiki/4)-Unity-Tasks),但不明白如何将它用于我的案例。 我在看例子,觉得自己很白痴。 我试图自己编写线程和协程的混合,但现在只是把完整的代码弄得乱七八糟,没有任何工作结果=(

任何人都可以给出我的案例的任何简单示例:当统一对象在其他线程中进行一些计算时,得到它的工作结果并继续“正常行为”。

【问题讨论】:

  • Unity3D 中绝对没有线程。这些信息在数以百万计的 QA 上广泛可用。 (您提到“协程”——它们与线程完全没有任何联系。协程与等待下一个图形帧有关,与处理没有任何联系。)
  • 其次请注意,您需要一个“单独的 CPU”来为棋盘游戏执行“AI”是不可思议的。它不在现实的范围内,它会超出 10,000 倍。
  • 第三,你只需要 google "google.com/search?q=asset+store+threading" 就可以立即找到 Unity 的线程包。如果(难以置信地)您需要进行数学计算等,这就是您的答案。 (难以想象你会从头开始编写自己的线程系统 - 就像你从头开始编写渲染器或物理一样!)
  • 请注意,在 .NET2 中,我们主要使用 BackgroundWorker 来处理这样的工作 - 使用原始 Threads 是一个巨大的痛苦。 BackgroundWorker 为您提供了一种将结果和错误编组回源同步上下文的简单方法,例如,您可以很容易地利用这种方法在 Unity 的协同程序框架之上创建自己的伪任务。
  • @Programmer 你有没有尝试过为棋盘游戏或任何其他游戏编写任何类型的人工智能?您认为仅在玩家按下“结束回合”时才开始计算是个好主意吗?你认为停止玩家的游戏 10 秒是个好主意吗,而 2 秒是可能的?还是零?

标签: c# multithreading unity3d coroutine


【解决方案1】:

我找到了解决方案,混合了线程和协程。

我不太喜欢 C# 中的线程式编程,因为返回的结果不是很容易理解 - 代码不好。

所以,这是我的解决方案,使用 Foundation.Tasks

想象一下,例如,我们有一些 MonoBehaviour 子类,做一些繁重的计算。

UnityTasks 之前的代码

public class ExampleClass : MonoBehaviour {
  public bool MyHeavyCalculator(bool exampleArg)
  {
    //loong and heavy calculations
  }

  public void SomeFunc()
  {
    //and here we get freezing
    if (MyHeavyCalculator(boolArg))
    {
      //unfreeze here
    }
  }
}

代码,使用 Foundation 中的 UnityTask

//in my case, heavy calculations are static in another class
public static class Calculator
{
  public static bool DoHeavy(bool exampleArg)
  {
    //loong and heavy calculations
  }

}

public class ExampleClass : MonoBehaviour {

  IEnumerator coroutineSomeFunc()
  {
    bool result = false;
    //code to show "thinkng sign"
    UnityTask t = UnityTask.Run( () => {
      //and no freesing now
      result = Calculator.DoHeavy(myArg);
    });
    yeild return t;
    //code to hide "thinkng sign"
    if (result)
    {
      //continue game flow
    }
  }

  public void SomeFunc()
  {

    StartCoroutine(coroutineSomeFunc());
  }
}

此外,Foundation.Tasks 让我可以轻松选择策略(协程、后台线程),而且我可以毫无问题地获得计算结果,而且我的代码很好且易于理解(恕我直言)

【讨论】:

猜你喜欢
  • 1970-01-01
  • 2017-10-25
  • 2012-11-23
  • 1970-01-01
  • 2020-08-29
  • 2013-04-10
  • 2020-05-18
  • 2016-06-07
  • 2011-07-10
相关资源
最近更新 更多