Порядок кадров

From Valve Developer Community
Jump to: navigation, search
English

Движок

Движок имеет два режима работы - потоковый (многопоточный) и безпотоковый (однопоточный). Переменная host_thread_mode определяет, какой режим работы будет использован. Выделенные сервера игнорируют эту переменную и всегда используют безпотоковый (однопоточный) путь. XBox 360 по-умолчанию работает в потоковом режиме, в то время как ПК по-умолчанию работает в безпотоковом. Потоковый режим был введен вместе с Orange Box версией движка, и не существовал в Episode 1 или в предыдущих версиях.

Сервера-слушатели (listenservers) (например однопользовательские игры или сервера запущенные одним из игроков) выполняют все секции кода, вызывая функции из client.dll и server.dll в одном и том же цикле работы движка. Клиенты, подключенные к удаленному серверу могут выполнять только помеченные курсивом секции, а выделенные (dedicated) сервера могут выполнять только секции выделенные жирным. Сборки выделенного (dedicated) сервера (Linux или Windows SrcDs) могут выполнять только подчеркнутые секции.

Обозначения:

  • Жирный - код сервера, работает на любом сервере, только для серверов или серверов-на-клиентах
  • Курсивом - код клиента, работает на любом клиенте, только для клиента или серверов-на-клиентах
  • Подчеркнуто - код для выделенного сервера (Не подчеркнутые элементы не выполняются на выделенном сервере)
  • Зеленым - функции вызываемые движком внутри игрового кода

Безпотоковая модель

Потоковая модель

Секции

Обозначения:

  • Зеленым - функция вызываемая движком внутри игрового кода
  • Пурпурным - код существующий внутри игрового кода и доступный для изменения
  • Красным - специальная информация

Device input

Эта секция читает сообщения от операционной системы и указателей клавиатуры и события окна.

События кнопок отправляются по очереди сначала утилитам (PET, Actbusy и т.п.), затем к системе VGUI, клиентскому коду игры, и наконец движку. Если один из элементов цепи не может обработать полученное событие, то оно отправляется на обработку следующему звену.

  • При нажатии кнопки: CHLClient::IN_KeyEvent

Console commands

В этой секции подсчитываются и исполняются команды, введенные в игровую консоль. Если консольная команда это команда созданная игровым кодом, она выполнит возврат внутри игрового кода через ConCommand::Dispatch( const CCommand &command ) в файле convar.cpp.

Networking

В этой секции отправляются и принимаются сетевые сообщения. На сервере локального хоста она работает через локальную петлю (loopback). На экземплярах только для серверов или только для клиентов работает через соединение по протоколу UPD. Игровой код не вызывается в этой секции.

Input

Эта секция читает и исполняет входящие сообщения. Она работает только на клиенте или локальном хосте.

  • CHLClient::HudProcessInput()
  • Обработка console commands
  • Обработка команд перемещения игрока
    • CHLClient::CreateMove()
    • Помещение команд перемещения в очередь для передачи по сети на сервер

Server game code

Эта секция вызывает функции Think для каждой сущности и выполняет игровую логику.

  • Если это последний такт фрейма: CServerGameDLL::Think()
  • Читает сетевой ввод
  • Для каждого плагина: IServerPluginCallbacks::GameFrame()
  • CServerGameDLL::GameFrame()
    • Для каждой игровой системы: FrameUpdatePreEntityThink()
    • GameRules::Think()
    • Симуляция физики
      • Для каждого игрока: CBasePlayer::PlayerRunCommand()
    • Для каждой игровой системы: FrameUpdatePostEntityThink()
  • Если это последний такт фрейма: (Эта часть кода выполняется в отдельном потоке если движок работает в потоковом режиме.)
    • CServerGameDLL::PreClientUpdate()
      • Для каждой игровой системы: PreClientUpdate()
    • Передача очередных сетевых сообщений
    • Для каждого клиента:
      • Настройка упаковки данных для сети
        • CServerGameClients::ClientSetupVisibility()
        • CServerGameEnts::CheckTransmit()
        • В одиночной игре, Client logic работает через локальный сетевой интерфейс (используя memcpy вместо медленной сетевой петли)
        • Измененные таблицы данных сущностей упаковываются для передачи по сети и снимки (snapshots) отправляются клиентам
    • CServerGameClients::PostClientMessagesSent()

Client logic

Эта секция читает сетевые пакеты и обновляет сущности на клиенте.

  • Читает пакеты
    • Если сообщение является пакетом сущности:
      • Если это мультиплеер или особая команда:
      • CPrediction::PreEntityPacketReceived
      • CHLClient::FrameStageNotify(FRAME_NET_UPDATE_START)
        • Запрос на проверку векторов и углов
      • Обновление базовых данных, обновление таблиц данных сущностей
        • При необходимости вызов C_BaseEntity::PreDataUpdate.
      • CHLClient::FrameStageNotify(FRAME_NET_UPDATE_POSTDATAUPDATE_START)
      • Для каждой обновленной сущности: C_BaseEntity::PostDataUpdate()
      • CHLClient::FrameStageNotify(FRAME_NET_UPDATE_POSTDATAUPDATE_END)
        • CPrediction::PostEntityPacketReceived()
      • Если сущность вошла или вышла из потенциально видимый набор: C_BaseEntity::NotifyShouldTransmit()
      • CHLClient::FrameStageNotify(FRAME_NET_UPDATE_END)
        • Запрос на повторную проверку векторов и углов
      • CPrediction::PostNetworkDataReceived()
    • Если сообщение это сообщение сущности:
      • CHLClient::DispatchUserMessage()
    • Если сообщение это игровое событие:
      • ClientModeShared::FireGameEvent()

Client prediction

Эта секция выполняет код прогнозирования для локального клиента.

  • CPrediction::Update()
    • Выполнение прогнозирования. Для каждой команды перемещения игрока:
      • CPrediction::RunSimulation()
      • Для каждой прогнозируемой сущности:
        • Если таблица была изменена: C_BaseEntity::OnPreDataChanged()
        • C_BaseEntity::PhysicsSimulate()
          • CPrediction::RunCommand()
          • Если сущность это игрок:
            • C_BasePlayer::PreThink()
            • CPrediction::SetupMove()
            • CGameMovement::ProcessMovement()
            • CPrediction::FinishMove()
            • C_BasePlayer::PostThink()
            • CMoveHelperClient::ProcessImpacts()
          • Если сущность это не игрок:
            • Запуск физической симуляции и C_BaseEntity::Think()
    • CPrediction::Untouch()

  • Обновление углов в соответствии с исходными данными
    • CPrediction::SetLocalViewAngles()
  • CHLClient::ExtraMouseSample()

Rendering

Настройка отрисовки видимого мира, обновление всех сущностей и отрисовка сцены и пользовательского интерфейса.

  • CHLClient::FrameStageNotify(FRAME_RENDER_START)
    • CInput::CAM_Think()
    • CViewRender::OnRenderStart()
      • CViewRender::SetUpView()
        • CBasePlayer::CalcView()
      • Для каждого игрока: CBasePlayer::UpdateClientSideAnimation()
        • CMultiPlayerAnimState::Update()
      • ProcessOnDataChangedEvents()
        • Для каждой сущности с изменившимися данными: C_BaseEntity::OnDataChanged()
      • Обновление сущностей, временных сущностей (tempents), систем частиц, симуляция физики, вызов функции ClientThink()
  • CHLClient::View_Render()
    • Рисует мир и пользовательский интерфейс
  • CHLClient::FrameStageNotify(FRAME_RENDER_END)

Sound

Код обработки звука и воспроизведение звуков на клиенте. Это не делает вызовы в коде игры.

Client HUD update

Эта секция вызывает:

  • CHLClient::HudUpdate()
    • Обновление HUD и игровых систем