Странная проблема заикания с многопоточностью - PullRequest
2 голосов
/ 25 мая 2011

Я изменил свою физику из последнего поста: Обновление физического движка в отдельном потоке, разве это разумно? примерно так:

public void PhysicsThread()
{
    int milliseconds = TimeSpan.FromTicks(333333).Milliseconds;
    while(true)
    {
        System.Threading.Thread.Sleep(milliseconds);

        world.Step(milliseconds / 1000.0f);
    }
}

Как и прежде, он работает самостоятельнонить.Я нахожу что-то странное, что я не уверен, что я полностью понимаю, это немного сложно объяснить, поэтому я сделал видеозапись этого: http://www.youtube.com/watch?v=qFf6oSRfVt8

Если вы посмотрите внимательно, вы увидите, что объектвыстрел из пушки иногда заикается и, кажется, движется назад на заданное расстояние.Это заметно только на быстро движущихся объектах (таких как стреляющий снаряд).

Это полностью сбило меня с толку.Я даже создал систему, в которой я кеширую положение тел в игровом логическом потоке, так что, поскольку физический поток может обновлять позиции тел, это не повлияет на позиции, считываемые игровой логикой, пока не будет вызвана функция обновления внутриигровая логическая нить, которая обновляет позиции физических тел для чтения игровой логики.

Есть идеи, какой аспект многопоточности может вызывать эту проблему?Я не думаю, что это физический движок, обновляющий позиции тел во время игровой логики и рисования, как я уже упоминал, я кеширую это, и оно остается постоянным на протяжении всего ...

Ответы [ 2 ]

2 голосов
/ 25 мая 2011

Мое первое предположение состоит в том, что у вас может быть классическое состояние гонки, когда несколько потоков соревнуются за обновление позиции объекта без гарантий блокировки или упорядочения.

Вы можете проверить Википедию, чтобы узнать больше об условиях гонки, блокировкии другие основы многопоточности / многопроцессорности.

Трудно сказать больше, не видя больше вашего кода, особенно той части, которая выполняет обновление.

Редактировать: Oneчто вы можете сделать, это сохранить DateTime.Now в каждом цикле и сравнить его с предыдущим значением.Если ваши временные задержки несовместимы, вы увидите это.

Еще одна вещь, которую нужно проверить, - узнать, сколько времени занимает выполнение вашей функции world.Step () (снова с использованием DateTime.Now и некоторой регистрации, или как угодно).

Если оба из них указывают на согласованное время, то моё подозрение упадет на физический движок.Проверьте положение объекта до и после вызова world.Step (), и если вы видите какие-то странные прыжки, которые должны указать вам, где искать.

1 голос
/ 25 мая 2011

Вероятно, это должен быть комментарий, но будет трудно опубликовать код.Если вы пытаетесь работать в реальном времени, то этот код подвержен дрожанию времени, поскольку нет гарантии, что Thread.Sleep будет спать в течение заданного времени.Я бы использовал секундомер, чтобы измерить прошедшее время и использовать его для управления вашим миром.

public void PhysicsThread()
{
    int milliseconds = TimeSpan.FromTicks(333333).Milliseconds;
    var stopwatch=System.Diagnostics.Stopwatch.StartNew();

    while(true)
    {
        System.Threading.Thread.Sleep(milliseconds );

        world.Step(stopwatch.ElapsedTicks);
        stopwatch.Restart();
    }
}
...