CPU 负载高一般是游戏的逻辑处理比较复杂, 这里所谓的「逻辑」基本涵盖了游戏里玩家无法直接"看到"的所有运算, 例如 AI 行为, 伤害计算, 寻路等等...
这部分确实是比较难"优化"的. 最主要的原因是要保持游戏中所有"对象"的状态一致, 而这种一致性跟「时序」(简单来说就是顺序吧)紧密相关. 例如 A 首先击杀了 B, 那么理论上 B 应当无法再动作了 - 比如说应该就无法再击杀 A - 当然游戏也可以设计成子弹有飞行时间(或者比如是用火箭筒之类的武器) 但是在这种情况下击杀的行为是绑定在这个 projectile 上的, 而非 A 或 B, 那么对于这种情况我们要保证的一致性就是 B 在发出 projectile 的时候还没有死掉.
还有比如说你可能要维护一个"全局"的 Game Mode 对象, 比如记录每个队伍的得分/抢点模式下各个点的进度等等整盘游戏共享的一些状态, 对于这些状态的更新必须准确及时而且很多时候先后顺序至关重要, 而这些放在多线程里很难正确地实现.
多核和多线程是不同的概念, 首先单核也可以运行多个进程(多线程亦适用), 也许你听说过「抢占式多任务操作系统」这么个概念, 即系统会根据优先级/时间切片等等条件不停地切换不同的进程运行. 这也是为什么在以前只有单核的 CPU 上我们也可以同时运行多个软件. 多核只是让调度器可以有更多的选择, 即(理论上)可以真正的"同时"运行若干个任务, 例如你玩的游戏和用的聊天软件就可以互不干扰的同时运行了(单核的话例如说各占用 50% 的 CPU 时间). 多线程和多核正好对应了「并发」 (Concurrency) 和 「并行」 (Parallelism) 这两个藕断丝连的概念. 另外这里讨论的进程在多核上并行是比较简单的, 多线程想要真正利用多核还有更多的限制.
对于开发者来说, 编写多线程的代码本身就不是一个容易的事, 这也是为什么有所谓「线程安全」的库/数据结构等等. 在此之上如何去同步多个线程上产生的状态更新是更大的难题, 想要维持一个有先后顺序, 或有依赖关系的逻辑能正确计算, 最简单最直观的方法就是只用一个线程(这样也是最方便调试的).
当然以上都是在讨论「逻辑线程」, 其实现在的软件/游戏基本上不存在"单线程"的了. 哪怕是 iPhone 上最简单的 App, 其渲染和逻辑也是在不同的线程里面. (虽然说到底还是要看开发者能不能正确实现多线程的一些行为) 对于游戏来说渲染/动画/声音/UI都可能在不同的线程上, 这也会有同步的问题, 当然一般而言这些不同职责的系统之间依赖会更少/更简单.
如果谈论「用多线程优化」的话, 我觉得最重要的就是去解决不同线程之间的状态同步问题. 如果某些逻辑能够分割成若干可以同时运算而又互不冲突的部分, 那应该可以相对简单地"优化".
其实我个人的观点是不妨带着并发/并行的思路去设计游戏, 去考虑游戏里的这些状态能否接受不同步或者能否接受一定程度的不同步等等.
淡观天下 1年前
aquarhead [作者] 1年前
淡观天下 1年前
发布