我已经在寻找答案,但是我无法找出处理昂贵函数/计算的最佳方法。
在我当前的游戏(基于2d瓷砖的城市建筑物)中,用户能够放置建筑物,建造道路等。所有建筑物都需要与用户必须放置在地图边界处的路口相连接。如果建筑物未连接到此路口,则在受影响建筑物上方将弹出“未连接到道路”标志(否则必须将其删除)。大多数建筑物都有半径,并且可能彼此也有关联(例如,消防部门可以帮助半径30瓦范围内的所有房屋)。这也是我在公路连接发生变化时也需要更新/检查的内容。
昨天我遇到了一个很大的性能问题。让我们看一下以下情况:用户当然也可以删除建筑物和道路。因此,如果用户现在在连接点之后立即断开连接,则需要同时更新许多建筑物。我认为第一个建议是避免嵌套循环(在这种情况下,这绝对是一个重要原因),但是我必须检查一下...
- 如果在拆除路砖的情况下建筑物仍连接到路口(我仅对那条路受影响的建筑物这样做)。(在这种情况下可能是一个较小的问题)
半径图块列表,并获取半径范围内的建筑物(嵌套循环-大问题!)。
// Go through all buildings affected by erasing this road tile. foreach(var affectedBuilding in affectedBuildings) { // Get buildings within radius. foreach(var radiusTile in affectedBuilding.RadiusTiles) { // Get all buildings on Map within this radius (which is technially another foreach). var buildingsInRadius = TileMap.Buildings.Where(b => b.TileIndex == radiusTile.TileIndex); // Do stuff. } }
所有这些使我的FPS 从60降低到一秒钟几乎达到了10。
我也可以。我的想法是:
- 没有为此使用主线程(更新功能),而是另一线程。当我开始使用多线程时,可能会遇到锁定问题。
- 使用队列来处理大量计算(这种情况下最好的方法是什么?)
- 在我的对象(建筑物)中保留更多信息,以避免进行更多计算(例如,半径范围内的建筑物)。
使用最后一种方法,我可以在此foreach中删除一个嵌套形式:
// Go through all buildings affected by erasing this road tile.
foreach(var affectedBuilding in affectedBuildings) {
// Go through buildings within radius.
foreach(var buildingInRadius in affectedBuilding.BuildingsInRadius) {
// Do stuff.
}
}
但是我不知道这是否足够。如果玩家拥有大地图,像城市天际线这样的游戏必须处理更多建筑物。他们如何处理这些事情?由于并非所有建筑物都同时更新,因此可能存在更新队列。
我期待您的想法和意见!
非常感谢!