【发布时间】:2021-07-23 22:24:59
【问题描述】:
最近我正在为多人游戏开发门系统,但我遇到了门 ID(指定要与哪个门交互)的问题。我想避免手动分配 ID,因为我的游戏有很多门,所以我找到了一个解决方案 - 而不是不可靠的 FindObjectsOfType,我构建了以下场景循环:
void IterateThroughScene(Scene scene)
{
SortedList<string, NetworkedObject> sortedObjects = new SortedList<string, NetworkedObject>();
//List<CrossSceneAudioSyncListener> audioListeners = new List<CrossSceneAudioSyncListener>();
foreach (GameObject sceneRootObject in scene.GetRootGameObjects())
{
foreach (NetworkedObject netObj in sceneRootObject.GetComponentsInChildren<NetworkedObject>())
{
Vector3 position = netObj.transform.position;
string transformHash = position.x.ToString("0.00") + position.y.ToString("0.00") + position.z.ToString("0.00");
transformHash = Hashing.MD5(transformHash);
sortedObjects.Add(transformHash, netObj);
//CrossSceneAudioSyncListener audioListener = netObj.GetComponent<CrossSceneAudioSyncListener>();
//if(audioListener != null) audioListeners.Add(audioListener);
}
}
//CrossSceneAudioSyncInstance.LoadObjects(audioListeners);
Dictionary<ushort, NetworkedObject> preparedObjects = new Dictionary<ushort, NetworkedObject>();
ushort lastId = _ids[scene.name];
foreach (var part in sortedObjects)
{
NetworkedObject preparedObject = part.Value;
preparedObject.GetObjectData().id = lastId;
preparedObjects[lastId] = preparedObject;
lastId++;
}
_ids[scene.name] = lastId;
_registeredObjects[scene.name] = preparedObjects;
}
这里我一步一步列出这个方法的作用:
- SortedList 被实例化以保存对象
- 2 个 foreach 正在获取场景中的所有对象
- 这里脚本生成位置的MD5并添加到SortedList中
- 之后,创建 Dictionary 实例来保存最终数据
- 下一个 foreach 完成,循环通过 SortedList 并以可靠的方式分配 NetworkedObject ID。
这在中小型场景中做得很好,但我开始在大型场景中遇到严重问题 - 我有一台很好的 PC 并且迭代需要 12 秒,我的游戏目标是中型 PC .
那么,你知道如何优化这个算法吗?
【问题讨论】:
-
你能不能只标记所有的门并使用FindGameObjectsWithTag。我不知道内部
FindObjectsOfType是如何工作的,所以我无法比较这段代码的有效性。我能想象的唯一让搜索更有效的地方是修剪。您正在遍历场景中的每个对象,然后获取每个具有组件的子对象。您可以让门将所有根父节点标记为有门以便于查找。 -
FindObjectOfType 不是一种可靠的方法。它可能以不同的顺序返回对象,这是不可接受的,有时我别无选择并且需要使用子对象
-
或者,与其在大海捞针中寻找针,不如让针告诉你它自己。您可以让门获取门管理器的引用,然后让它在调用函数时分配 id,或者使用静态实例实现 Singleton Pattern。
-
不保存值是什么意思?你很可能不是marking the scene as dirty。如果您确实需要在运行时执行此操作,请制作一个异步加载屏幕,并在需要时将其扔掉。我建议废弃它并制作一个编辑器工具。
-
@TEEBQNE 感谢 MarkSceneDirty!现在编辑器脚本按预期工作!这个算法现在没用了。
标签: c# algorithm unity3d optimization