ReactiveX视频游戏渲染循环计时

时间:2018-02-21 12:35:16

标签: timestamp event-loop reactivex rx.net

我目前正在调查.net中的反应性用于模拟重型视频游戏。我的第一个目标是创建基本的事件/渲染循环。我有以下代码几乎完全符合我的要求。

var frames = Observable
    .Interval(TimeSpan.Zero, new EventLoopScheduler())
    .Timestamp()
    .Select(timestamp => new Frame
    {
        Count = timestamp.Value,
        Timestamp = timestamp.Timestamp.ToUnixTimeMilliseconds()
    });

frames.Subscribe(frame =>
{
    Console.WriteLine($"GameObject 1 - frame.Count: {frame.Count} frame.Timestamp: {frame.Timestamp}");
});

frames.Subscribe(frame =>
{
    Console.WriteLine($"GameObject 2 - frame.Count: {frame.Count} frame.Timestamp: {frame.Timestamp}");
});

frames.ToTask().Wait();

这会在主线程上尽快发出帧事件。完善!但是,我注意到两个订阅者之间的时间戳可能会略微偏离同一帧。例如,

GameObject 1 - frame.Count: 772 frame.Timestamp: 1519215592309
GameObject 2 - frame.Count: 772 frame.Timestamp: 1519215592310

同一帧的时间戳为1毫秒关闭。为此,两个游戏对象/订阅者都需要在每个帧中获得完全相同的时间戳,否则模拟可能无法正常运行。

我猜测每个订阅者正在为流中发出的每个事件评估一次Timestamp运算符。是否有办法获得它,以便每个事件发出的所有订阅者评估一次?谢谢!

1 个答案:

答案 0 :(得分:1)

Whelp,我应该再给它几分钟的文档阅读。

解决方案是让我的框架事件流可连接。我所要做的就是在附加订阅者之前发布框架事件流。然后在事件循环开始之前调用Connect。完善!该死的Rx很棒。

var frames = Observable
    .Interval(TimeSpan.Zero, new EventLoopScheduler())
    .Timestamp()
    .Select(timestamp => new Frame
    {
        Count = timestamp.Value,
        Timestamp = timestamp.Timestamp.ToUnixTimeMilliseconds()
    })
    .Publish();

frames.Subscribe(frame =>
{
    Console.WriteLine($"GameObject 1 - frame.Count: {frame.Count} frame.Timestamp: {frame.Timestamp}");
});

frames.Subscribe(frame =>
{
    Console.WriteLine($"GameObject 2 - frame.Count: {frame.Count} frame.Timestamp: {frame.Timestamp}");
});

frames.Connect();

frames.ToTask().Wait();