【Unity性能优化】在Unity中使用线程:实践与注意事项

众所周知,Unity有自己的主线程,所有的生命周期函数和特性都在那里执行。早期,我们被告知尽量避免使用线程,而尽可能使用协程(Coroutine),因为Unity不是线程安全的。然而,协程并不总能发挥作用,尤其是在主线程的生命周期中运行的特定时段。考虑那些阻塞线程的执行场景。如果我们在主线程中进行套接字连接,应用程序将会卡住。在处理一个文件传输的bug时,我发现了在Unity中使用线程(Thread)时一些重要的注意事项。因此,我们应该在Unity中正确且安全地使用线程。

修复线程停止的Bug

我修复的bug与停止线程有关。我发现调用Thread.Abort()来停止先前的线程,然后使用Thread.Start()来启动具有相同任务函数的新线程,会在任务函数中的变量中导致意想不到的结果。

Thread taskThread;

void Task() {
  // 执行某些操作,并拥有局部变量。
  while(true) {
    // ...
  }
}

void StartTask() {
  if (taskThread != null && taskThread.IsAlive)
    taskThread.Abort();
  taskThread = new Thread(Task);
  taskThread.Start();
  // 在Task()中的局部变量出现了一些意想不到的结果
}

// 在Unity的MonoBehaviour中的某处调用
StartTask();

也许我应该等待一段时间后再调用Thread.Abort()来检查Thread.IsAlive。但有更好的方法来停止线程。设置一个布尔标志!调用Thread.Abort()可能会抛出ThreadAbortException异常。因此,我的解决方案如下:

bool runThread = false;
Thread taskThread;
Coroutine startTaskCoroutine;

void Task() {
  // 执行某些操作,并拥有局部变量。
  while(runThread) {
    // ...
  }
}

IEnumerator StartTask() {
  runThread = false;
  while(taskThread != null && taskThread.IsAlive)
    yield return null;

  runThread = true;
  taskThread = new Thread(Task);
  taskThread.Start();
}

// 在Unity的MonoBehaviour中的某处调用
if (startTaskCoroutine != null)
  StopCoroutine(startTaskCoroutine);
startTaskCoroutine = StartCoroutine(StartTask());

结论

  • 我们应该在什么情况下使用线程而不是协程
    1. 阻塞主线程的执行。
    2. 可以在后台运行的复杂计算。
    3. 与没有Unity API的原生代码插件通信。
  • 需要注意什么?
    1. 避免在自定义线程中使用Unity API。
    2. 使用布尔标志来停止线程,而不是Thread.Abort()
    3. 注意lock()的使用。
  • 10
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Unity打怪升级

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值