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

Efficient method for logging time series data in Unity3D?

我想在每次更新时以 .csv 格式记录多个项目。以前我用两种不同的方式做到了这一点:

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

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

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

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

Link 如果使用 NLog,特定于 CSV 布局设置:https://github.com/NLog/NLog/wiki/CsvLayout

为格式化提供了灵活性。效率是您需要根据比较测试运行来衡量的东西。加上根据您的需要提供归档日志文件的选项。

嗨,

另一种方法可能是使用像 "LabStreamingLayer" 这样的数据采集框架。您会在我的 github account.

上找到一个微小的实现

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

[编辑] 你是绝对正确的。抱歉拍的太快了...所以这里是更全面的答案:

LabStreamingLayer (LSL) 框架是高分辨率时间序列的数据采集框架。主要用于流式 EEG(脑信号...:))数据,通过网络保存和分析它们。它通过网络实现时间同步,因此可以合并数据流以进行进一步分析。 例如,我正在使用该框架获取 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 的文件中。有关详细信息,请参阅自述文件。

有关更多示例,请参阅从 LSL4Unity 存储库的自述文件中 link 编辑的 SDK 中的示例。 (抱歉,我的声誉很低,我不能直接 link 东西)。

所以,我希望这可能会有点帮助...:) 请考虑 LSL 的文档(github wiki 等)整个事情都有很好的记录!