【问题标题】:Most efficient / quickest way to handle data storing for an animation tool为动画工具处理数据存储的最有效/最快的方法
【发布时间】:2016-08-16 14:56:16
【问题描述】:

如果我有一堆可能是非线性但有序的值:1、3、8、12,然后我添加了一个新值,比如 5 什么是存储它的最佳收集类型(速度超过其他任何东西)在 3 到 8 之间并给我索引,这样我就可以直接检查该值后面和前面的内容。这是一个动画系统,我正在存储关键帧,我需要知道前面和后面的内容,以便正确插入值

目前我正在使用哈希表(字典),关键是存储关键帧的帧号,值是我想要的位置。

因此,使用这种方法,它对于在进行更改时更新关键帧非常有用,但是在制作动画时,如果我将 soem 数据放在 5 中,则找到 3 和 8 让我遍历整个列表以找出当前条目,然后存储上一个并迭代到下一个..(更不用说每次我向字典添加内容时,它都需要按键排序才能正常工作)。

只是寻找一些建议来解决这个相当开放的问题。

要深入了解我当前的动画工具结构:

我有一个称为时间轴的组件,它是 KeyframeProperties 记录的内容。因此,在关键帧属性中,您将调用 record() 并询问它所连接的时间线是否可以记录到当前插槽中,如果可以,它将返回记录关键帧的索引,然后返回关键帧属性将该索引存储到它当前拥有的字典中,其中包含动画师的当前数据。当您选择播放动画时,您调用了timeline.play() 函数,它将处理遍历所有连接的属性并调用keyframeproperty.advanceframe(int frame#)。这就是为什么我需要上一帧和下一帧,因为在不知道这一点的情况下,当帧#被传入时,没有办法知道动画的下一个插值目标应该在哪里..

示例:传入一个 4 并且属性中最近的两个关键帧在 3 和 7,动画应该将起始位置设置为第 3 帧数据,然后通过 0.25 (1/(7-3 ) = 0.25)

【问题讨论】:

  • 每帧有一个条目的数组怎么样。数组索引 == 帧号。任何数组位置都可以为空或包含关键帧属性。
  • 仍然存在需要注意关键帧属性中下一个最近帧的问题。这意味着我将遍历所有数组以找到下一个和上一个条目。要记住,在关键帧属性中推进一帧时,如果传入一个不存在的帧,它需要直接在之前和前面找到帧,以便找出它应该在动画中的位置
  • 你在说什么尺寸?两个分配的插槽之间的平均距离和最大距离是多少?
  • puu.sh/os7mF/e0d87fb291.png 时间线的平均值始终为 0。但是,可以将对象的关键帧插入该时间线内的任何位置。使用这张图片,如果我想从 3 到 13 开始制作动画。它会遍历并从 3s 位置动画到 4s,因为这两个都是实际的关键帧,而从 4 到 5 你必须假设从第 4 帧和第 13 帧位置之间的差异以及第 5 帧的位置
  • 是的,但我的意思是,这些数字有多大?如果在下一帧之前只有 10 帧或 100 帧,这应该不是问题。如果您有 10,000 或 100,000,这可能是个问题。请记住,今天的 CPU 每秒执行数十亿次操作。

标签: c# animation optimization unity3d collections


【解决方案1】:

就速度而言,数组与列表或字典之间没有区别,除非您要处理大量数据并在它们上密集地执行方法(比如每帧 100 次)。所以,别担心,只要使用任何让你更容易的东西,不要这样做Premature Optimization

【讨论】:

    【解决方案2】:

    我认为 .NET 中没有任何集合/容器可以返回插入项的索引。至少有序的不提供这种能力。

    您的问题确实比表面上看起来要复杂。因为,据我从您的问题的标签中可以看出,您的解决方案是针对 Unity,该解决方案使用了一个相当旧的 Mono 实现,该实现针对 .NET 3.5 配置文件。此外,由于 Unity 能够使用 IL2CPP 将您的 C# 代码转换为 C++(取决于您所针对的平台),您甚至可能需要考虑 C++ 编译器将如何处理您的代码,它是否会向量化您的代码。所以,很难给你一个直接的答案,但我会试一试......

    如果您的数据集很小(我会说少于几千个项目,这是一个取决于您的目标平台的相对数量),那么您几乎可以使用您选择的任何集合/容器,它不会产生很大的区别。如果是这种情况,那么我会选择LinkedList,因为它允许您通过一次搜索操作同时拥有您正在寻找的项目及其邻居(列表中的前一个和下一个项目)。在您的情况下,如果您有对包含关键帧 5 的 LinkedListNode 的引用,您将能够通过使用 LinkedListNode 对象的 Previous 和 Next 属性检查上一个和下一个关键帧的位置。就是方便……

    如果你有一个大数据集;首先,你更看重的是插入速度还是检索速度?不幸的是,它们走向相反的方向,所以你必须在那里做出选择。如果检索速度是你喜欢的,忘记 LinkedList 类,它对于迭代大量数据来说太慢了。但是,如果您喜欢插入速度,那么 LinkedList 也是一个不错的选择,因为它不必在每次向列表中添加值时对所有数据进行排序。您只需在您想要的位置插入一个项目,它所要做的就是在这里和那里更改一些指针。问题是您必须告诉它要将项目添加到的位置。这意味着,您仍然需要执行搜索才能找到要插入项目的位置,这将是昂贵的,但仍然不如诉诸数万个项目那么糟糕。

    如果您打算以 IL2CPP 为目标,那么我会忘记以上所有内容,并使用一个简单的数组并自己实现所有搜索、插入、排序、数组大小调整操作。因为数组上的搜索操作很可能会被 C++ 编译器向量化,这将为您提供大型数据集的巨大减速。

    【讨论】:

    • 嗨,塞尔坎。我可能会说,你可以完全删除你的答案并只输入:“try a LinkedList”。就这么简单。
    • 给鱼与教如何钓鱼乔……如果你想做后者,你必须解释你的答案背后的原因。不,如果您完整阅读,LinkedList 并不是我在回答中建议的唯一内容。
    猜你喜欢
    • 1970-01-01
    • 2018-01-05
    • 1970-01-01
    • 1970-01-01
    • 2017-08-06
    • 2010-09-22
    • 2010-10-21
    • 2016-01-14
    • 1970-01-01
    相关资源
    最近更新 更多