c# - 在大型 Unity/C# 游戏中过滤通用集合的理想性能
问题描述
我正在使用 Unity/C# 开发一款商业游戏,并且正在审查并熟悉代码。我开始对此感到疑惑,因为在很多情况下,您会持有一个充满诸如 GameObjects、Components 或 ScriptableObjects 之类的列表……例如,您可能在 RTS 游戏类中有这样的字段:
protected List<Unit> allUnits = new List<Unit>();
现在,假设在运行时触发了一个事件,您需要在其中循环allUnits
并操作某些事件,或者只选择您想要的某些事件,甚至确定满足某个条件的事件的数量。请容忍我这个人为的例子,但 3 种标准方法是 for-loop、for-each 或 Linq 扩展方法/查询语句。假设我想找到所有未受重伤或死亡且弹药不足的单位。我可以使用以下方法来处理这个问题:
for ( int i = 0; i < allUnits.Count; i++ ) {
var next = allUnits[i];
if ( next.IsDead ) continue;
if ( next.IsCriticallyWounded ) continue;
if ( next.AmmoCount >= Magazine.MaxCapacity * 3 ) continue;
else
unitsLowOnAmmo.Add( next );
}
您可以在循环中使用相同的逻辑foreach( var next in allUnits )
,所以我不会再重复相同的代码。但是另一种方法是这样的,使用 Linq 扩展:
unitsLowOnAmmo = allUnits.Where( u =>
!u.IsDead &&
!u.IsCriticallyWounded &&
!u.AmmoCount >= Magazine.MaxCapacity * 3 ).ToList();
您还可以使用此语法查找 AI 控制下的所有内容,例如:
var aiUnits = (from Unit u in allUnits
where u.AIControlled
select u).ToList();
在另一种情况下,您可能需要找到满足一组条件的单位总数,例如我想找到所有受重伤的 AI 控制单位,以便他们可以派出医务人员或尝试将他们带到安全的地方野战医院。所以我可以通过使用累加器来做到这一点,比如for ( int i = 0, count = 0; i < allUnits.Count; i++ )
然后检查错误的条件和continue;
循环,否则如果它通过过滤器则让它落入一条count++;
语句。或者,显然,我可以使用int count = List<T>.Count( u => cond1 && cond2 );
...
现在,很明显,Linq 的东西更干净,更有表现力,代码也更容易阅读和维护,但我们都听过聪明的 C# 大师说“Linq 性能很差!永远不要使用 Linq!” 这些年来。而且我想知道对 Linq 的偏见到底是真是假,以及这些不同方法的表现如何真正不同并在“现场”表现。我正在处理一个非常大的项目,其中包含大约 24GB 的资产、代码和数据,它非常复杂,并且类中有很多 List 实例,用于存储经常需要迭代、过滤或计数的各种内容。在某些情况下,它是逐帧的,而在其他情况下,它是在特定的时间量之后或在事件或方法调用之后。
任何人都可以对性能比较有所了解,以及最好的方法是循环遍历集合以最高效的方式过滤、选择和计数它们吗?也许还有一种我在这里没有提到的更好的方法可能会更好?我已经阅读了这里(和其他网站)上的一些文章,这些文章并没有详细回答这个问题,让我对此感到满意。在离开一段时间后,我也刚刚了解了 C# 和 .NET 中的所有最新内容,我不确定框架(或语言)是否有任何可能完全改变事情的变化人们过去常说 Linq。我听说 Microsoft 吹嘘在 .NET 的许多领域都有性能改进,我想知道这些收益是否与这种情况有关。
解决方案
推荐阅读
- tensorflow - TensorFlow - 在 TF1.14 中,我如何将 RaggedTensor 变成张量或如何填充它?
- azure - Azure 数据工厂 - 启用 git n azure 数据工厂时,触发器不起作用
- angular - 无法绑定到 Angular 9 自定义指令
- java - 后台线程中的进度条.setProgress(variable)
- snakemake - 从配置文件传递通配符约束字典
- python - ID不同时的Web Scraping产品
- ios - 将变量从 ViewController 传递回前一个,但变量没有更新?
- swift - UITableView Swift 所需的设计建议
- python - python中的&位操作
- keras - 将填充数据返回 LSTM