我正在开发一款游戏,需要一种有效的方法来使用标签集合从大集合中选择记录子集。
有一个 3k+ 的声音集合,每个声音都带有许多简单的标签。集合在启动时加载一次,并且在运行时不会更改,但是,它可能会随着每个新构建而更改。
在运行时,我需要对游戏中发生的某些事件做出反应。这意味着我需要使用一组描述该事件的标签来检索最适合该事件对游戏世界的影响的声音。过滤标签可能有包含标签和排除标签。
这不是什么大问题,可以使用相对简单的 Linq 来解决。但我担心的是这段代码会在游戏循环中运行。单个帧中可能会发生任意数量的事件,因此最快的声音搜索/获取时间对于避免在游戏中的“事件繁重”时刻出现严重的帧丢失至关重要。
我不希望在每一帧都这样做,但很可能在一帧期间会发生多个事件。
现在这里是声音集合的样子:
audio-human-fall-01 <fall, impact, fatal>
audio-human-fall-02 <fall, floor, gear, impact>
audio-human-fall-03 <floor, fall, impact>
audio-human-fall-04 <fall, voiceover, fatal>
audio-human-fall-05 <fall, impact, floor, voiceover>
...
所以,在游戏过程中,我的角色摔倒了,我确定摔倒不会致命,角色会落在地板上。
我编写了一个如下所示的标签集:
<fall, floor, impact, -voiceover>
使用这样的过滤器,我希望获取以下声音:
audio-human-fall-02 <fall, floor, impact, gear>
audio-human-fall-03 <floor, fall, impact>
我还没有开始实施选择算法,因为我还在考虑如何解决这个问题。到目前为止,我正在考虑做这样的事情:
- 迭代声音的原始集合并构建一个
Dictionary<int, AudioClip>
键是标签哈希的地方; - 当我需要一个与一组标签匹配的声音时,我会从字典中查找所有具有我想要的标签哈希的 KVP;
- 完成后,我将得到一组可以合并然后分组的列表;
- 计数最高的组是与过滤器最匹配的 AudioClip;
- 排除不是问题,因为从不从字典中选择不必要的标签;
基本上我想知道这种方法一开始是否有好处,如果不是,什么是解决这个问题的更好方法。任何建议或朝着正确方向的推动将不胜感激。
PS:理论上/伪代码解决方案就可以了,不要找任何人为我做这项工作。只需要一些指导:D
编辑 1:
我发现了一些关于这个主题的有趣文章,似乎解决这个问题的最好方法是使用InvertedIndex
. 但是,仍然存在获取速度的问题,因为这InvertedIndex
需要对结果集进行联合操作。这可能会导致问题和严重丢帧。
根据我的一位同事的建议,我将首先尝试实现一些不同的东西。如果这确实有效,我会InvertedIndex
尝试这种方法。
所以,这个想法是创建一个Dictionary
(在启动时),它将包含对我收藏中声音的引用。对于给定声音可以具有的每个标签组合,每个声音都将由一个排序的标签哈希键作为键。
对于带有这些标签的声音:
audio-human-fall-02 <fall, floor, impact>
我最终会得到一本字典,其中包含以下内容:
<fall, floor, impact> audio-human-fall-02
<floor, fall, impact> audio-human-fall-02
<floor, impact, fall> audio-human-fall-02
<floor, impact, fall> audio-human-fall-02
<impact, floor, fall> audio-human-fall-02
<impact, fall, floor> audio-human-fall-02
<impact, floor, fall> audio-human-fall-02
<floor, impact, fall> audio-human-fall-02
<floor, fall, impact> audio-human-fall-02
etc...
优点:检索完美匹配的声音是瞬时的。
缺点:严重的启动开销和相对较大的查找字典。
谢谢, - 亚历克斯