Как сделать систему компонентов моей сущности безопасной для потока? - PullRequest
6 голосов
/ 24 июля 2010

В настоящее время я интегрирую систему компонентов сущности, как видно здесь , с физическим и графическим движками. До недавнего времени все было нормально, решая, что физика должна работать в своем собственном потоке. (Спасибо, Гленн Фидлер!)

Как и сейчас, я просто блокирую мьютекс, общий для всех подсистем, при доступе к компонентам.

Фрагмент из цикла физики:

lock_guard<mutex> lock( m_EntMutex );
entitymap::iterator it;
for ( it = m_Ents.begin(); it != m_Ents.end(); ++it )
{
    // Get physics component from entity
    // This is guaranteed to work ( component must exist for it to present in the map )
    shared_ptr<comp_phys> phys( static_cast<comp_phys*>( it->second->getComponent( COMP_PHYS ).lock().get() ) );
    // Get resulting Box2D vector
    b2Vec2 vec = phys->getBody()->GetPosition();

    // Get position component from entity
    // Same as above, but this is the component shared with the graphics subsystem   
    shared_ptr<comp_pos> pos( static_cast<comp_pos*>( it->second->getComponent( COMP_POS ).lock().get() ) );
    // Update position component from Box2D vector
    pos->setPosition( vec.x, vec.y, 0 );
}

Фрагмент из графического цикла:

lock_guard<mutex> lock( m_EntMutex );
entitymap::iterator it;
for ( it = m_Ents.begin(); it != m_Ents.end(); ++it )
{
    // Get position component from entity
    // This is shared with the physics subsystem
    shared_ptr<comp_pos> pos( static_cast<comp_pos*>( it->second->getComponent( COMP_POS ).lock().get() ) );
    // Get position from position component
    doubleVec3 vec = p->getPosition();

    // Get graphics component from entity
    shared_ptr<comp_gfx> gfx( static_cast<comp_gfx*>( it->second->getComponent( COMP_GFX ).lock().get() ) );
    // Update graphics component from position component
    gfx->getObject()->getParentSceneNode()->setPosition( float(vec.x), float(vec.y), float(vec.z) );
} 

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

Что было бы наиболее эффективным способом обеспечения плавного процесса обновления? Должен ли я позволить ему обновить весь мир за один раз или сделать что-то более инкрементное?

Редактировать: До меня дошло, что схема получения указателей несовершенна, но давайте предположим, что указатели действительны.

1 Ответ

2 голосов
/ 25 июля 2010

Когда речь идет о физических движках, работающих в игровых движках, я хотел бы предложить, чтобы у вас была точка синхронизации один раз за кадр, где вы копировали позиции / любую информацию, которая вам может понадобиться из физической системы в вашу систему компонентов. Назовите это дублированием буфера, если хотите. Внутренний и внешний экземпляр вашей позиции (мировая матрица / скорости и т. Д.).

Задержка до одного кадра на физических позициях - это не то, что заметит любой геймер.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...