在 Unity3D 中记录时间序列数据的有效方法

本文关键字:有效 方法 数据 时间序列 Unity3D 记录 | 更新日期: 2023-09-27 18:36:34

我想在每次更新时以.csv格式记录几个项目。以前我以两种不同的方式完成此操作:

  1. 打开并追加文件,然后在每次更新时将其关闭。
  2. 存储多个样本并定期批量记录它们。

这两种方法都达到了我想要的效果,但我想知道它们中的任何一种是否存在效率问题。

我应该完全使用其他方法吗?

在 Unity3D 中记录时间序列数据的有效方法

Hy,

另一种方法可能是使用像"LabStreamingLayer"这样的数据采集框架。你会在我的github帐户上找到一个小的实现。

我知道这个问题已经过时了,但 LSL 是一件很酷的事情,值得一试!此实现仍在开发中,但应该开箱即用。

[编辑] 你是绝对正确的。对不起,拍摄速度快...所以这是更全面的答案:

LabStreamingLayer (LSL) 框架是用于高分辨率时间序列的数据采集框架。主要用于通过网络流式传输EEG(Brainsignals...:))数据以保存和分析它们。它通过网络实现了时间同步,因此数据流可以组合在一起进行进一步分析。例如,我正在使用该框架在3D中获取对象的方向和位置数据,这些数据稍后将与EEG数据相关联。

要使用框架,您需要将 C# api(实际上只是 LSL.cs 文件)和 liblsl.dll 包含在 c# 项目中,然后只需几行代码即可将数据推送到 LSL。

using LSL;
public class LSLOutlet : MonoBehaviour
{
private liblsl.StreamOutlet outlet;
private liblsl.StreamInfo streamInfo;
private float[] currentSample;
public string StreamName = "Unity.ExampleStream";
public string StreamType = "Unity.Random01f";
public int ChannelCount = 4;
void Start()
{
    currentSample = new float[ChannelCount];
    streamInfo = new liblsl.StreamInfo(StreamName, StreamType, ChannelCount, Time.fixedDeltaTime);
    outlet = new liblsl.StreamOutlet(streamInfo);
}
public void FixedUpdate()
{ 
    currentSample[0] = Random.value;
    currentSample[1] = Random.value;
    currentSample[2] = Random.value;
    currentSample[3] = Random.value; 
    outlet.push_sample(currentSample);
}
}

outlet.push_sample(currentSample)将自动向示例集添加时间戳。关于 Unity 的固定更新方法,两个样本之间的时间应该或多或少是 appStartTime + tn -1 + Time.fixedDeltaTime。

另一方面,您需要一个实现以下功能的应用程序:

public class LSLInlet : MonoBehaviour {
liblsl.StreamInfo[] results;
liblsl.StreamInlet inlet;
int expectedChannels = 0;
void Start () {
    // wait until the expected stream shows up
    results = liblsl.resolve_stream("type", "Unity.Random01f");
    // open an inlet and print some interesting info about the stream (meta-data, etc.)
    inlet = new liblsl.StreamInlet(results[0]);
    expectedChannels = inlet.info().channel_count();
    Debug.Log(inlet.info().as_xml());
}
void FixedUpdate()
{
    // read samples
    float[] sample = new float[expectedChannels];
    while (inlet.samples_available() > 0)
    {
        inlet.pull_sample(sample);
        foreach (float f in sample)
            Debug.Log(string.Format("'t{0}", f));
    }
}
}

所以你会得到一个时间序列。您将能够自己保存数据,也可以使用LabRecorder - 它将流保存在一个简单的基于xml的文件中。有关详细信息,请参阅自述文件。

有关更多示例,请参阅 SDK 中的示例,该示例链接自 LSL4Unity 存储库的自述文件中。(很抱歉我的声誉不佳,我无法直接链接这些东西)。

所以,我希望这可能会有所帮助... :)请考虑 LSL 的文档(github wiki 等)。整件事都有据可查!

建议使用日志记录稳定/可靠的库,如 NLog 或 log4net

特定于 CSV 布局设置的链接(如果使用 NLog):https://github.com/NLog/NLog/wiki/CsvLayout

提供格式设置的灵活性。效率是您需要根据比较测试运行来衡量的东西。此外,还可以根据您的需要提供归档日志文件的选项。