首先,我必须说这是针对在线游戏服务器进行的,它可以跟踪地图中的每个对象,无论是玩家还是AI(NPC,或者你想要调用它)。
它不仅要跟踪它们,还要通知玩家近距离玩家。我已经解决了这个问题,而且我目前正在使用多线程方法,这种方法非常有效。
我将所有对象存储在哈希表中。我们可以认为哈希表是unordered_map
,虽然我实际上使用rde::hash_map
,因为它在插入和获取(自测试)时更快,但需要更多RAM(不是现在问题。)
问题是,该映射存储对象的唯一ID(64位),加上对象指针,如:
rde::hash_map<UInt64, Object*>
我的问题是:
我的应用程序(服务器)必须在一个循环(在一个线程内)中运行,这个循环必须每隔约50ms调用一次,以保持运行顺畅。循环代码如下所示:
void loop()
{
UInt32 prev = clock();
UInt32 prevSleep = 0;
while (1)
{
UInt32 diff = clock() - prev;
prev = clock();
maps.update() // Suppose map is a class, which stores the objects map
if (diff <= 50 + prevSleep)
{
prevSleep = 50 + prevSleep - diff;
sleep(prevSleep);
}
else
prevSleep = 0;
}
}
现在,到目前为止,函数map::update()
是导致循环增加到4500ms的函数。
每次调用更新时,映射对象都必须检查要添加到存储的新对象,如果添加了一个对象,该对象必须通知所有其他对象,我这样做(伪代码) :
foreach obectsToBeAdded as joiner:
foreach objectsList as object:
joiner->notify(object);
object->notify(joiner);
稍后,必须调用每个对象的内部更新,我这样做(再次伪代码):
foreach objectsList as object:
object->update();
而且,如果这还不够,上面的循环必须扩展为:
foreach objectsList as object:
object->update()
// Visit all the other objects
// Called once every 1 sec for the object, not on every call
foreach objectsList as other:
if other != object:
object->visit(other)
将第一个循环(添加和通知)与更新循环合并,如下所示:
foreach objectsList as object:
foreach objectsToBeAdded as joiner:
object->notify(joiner)
joiner->notify(object)
object->update()
// Called once every 1 sec for the object, not on every call
foreach objectsList as other:
if other != object
object->visit(other)
当对象计数不大时,这种方法很有效,一旦增加,循环开始需要4秒,这远远超过我正在寻找的50ms。
还有其他方法可以进一步优化吗?我虽然使用八叉树来跟踪地图中的物体位置,但后来得出的结论是它只会使问题恶化。
我还将每个地图划分为一个实体的35个单位(35个是&#34;视图范围&#34;,LOS),因此给定的rde::hash_map
仅包含相互看见,因此需要更新。只要对象数量很少就可以工作......
我还能做什么?谢谢!
所有这些foreach
都是使用迭代器的循环,例如rde::hash_map<...>::iterator
到objects.begin()
的{{1}}
其他优化,例如不更新,如果没有玩家(真实用户,而不是NPC),在没有玩家在给定地图上时释放内存,等等,已经被考虑在内
答案 0 :(得分:1)
除了空间分割之外,首先想到的优化是因为对象仅被告知它们附近的变化(例如使用四叉树):每个对象都必须被告知每次变化吗?为什么不告诉每个对象,'每一帧,我都会运行你的update
方法。在update
方法中,您可以查找所需的所有内容(例如,可能存在此帧/最近帧中发生的所有更改的缓冲区)并根据您的需要自行更新。这样,您就不会花费CPU周期来通知对象他们实际上不需要知道或关心的事情。
另外,您是否在程序中运行了CPU分析器,并验证了热点(最耗费CPU时间的地方)是您认为的位置?
请参阅意见以获得进一步讨论:
|
|
\|/
V