Работа с предсказанием
1 Вступление
2 Подробности
2.1 Передача по сети через таблицы данных
2.2 Создание таблицы предсказаний
2.1 Консольные комманды
2.1.1 cl_predictionlist
2.1.2 cl_pdump
3 Решение проблем
Вступление
Система предсказания (prediction) Source спроектирована с целью уменьшить влияние задержек на динамику игры. Наиболее чувтсвительны к задержкам события когда игрок нажимает клавиши (во время чего комманда отправляется на сервер и возвращается обратно), система предсказания Source имитирует эффект нажатия кнопки на клиенте немедленно. Когда после этого приходит ответ от сервера, клиент определяет корректная или нет спекулятивная имитация.
Основные требования которые требуется выполнить для того чтоб энтитя использовала систему предсказания:
Хорошее место для начала — рассмотреть пример кода оружия. Откройте файл src/game_shared/basecombatweapon_shared.cpp. Блоки #ifdef CLIENT_DLL и #ifdef GAME_DLL являются разделением кода между клиентским и сервером (условные директивы компилятора). Эти блоки указывают какой код компилируется для client DLL а какой для server DLL. Приведенный ниже код (сокращенный) соответствует шагу 2 описанной выше последовательности (помещает переменные измененные общим кодом в таблицу данных).
Таблица предсказаний описывает данные в вашей энтити которые должны быть одинаковые на клиенте и сервере когда клиент спекулятивно имитирует комманду. Это список переменных котрые передаются по сети и их типы. Если значение допустимое к отклонению от серверного (как в случае с значением с плавающе запятой которое передается с урезанным количеством бит), то вы можите указать на сколько допустимо отклонение. В коде приведенном ниже, это выполняется макросом DEFINE_PRED_FIELD_TOL macro.
Примечание: таблица предсказаний только требуется к наличии в client DLL, так что ограничте код при помощи #ifdef CLIENT_DLL.
Если вы добавляете функциональность к оружию и забываете выполнить шаги описанные выше, энтитя может сопровождаться рывками и страностями с анимацией. Ниже приводятся консольные комманды которые можно использовать для отладки в таких случаях. cl_predictionlist
Если ввести cl_predictionlist 1 в консоли, вы увидите графическое окно в верхнем правом углу. Оно отображает все энтити которые в данный момент используются системой предсказания Source (то есть: выполняющиеся одновременно на клиенте и сервере). левая колонка отображает индекс кажой энтити, средняя колонка отображает имя классов энтитей.
Как только будет определен индекс энтити, которую требуется отладить, используется cl_pdump. cl_pdump
Если установить значение cl_pdump к индексу предсказываемой энтити (из левой колонки в выводе окна cl_predictionlist), развернется обширный список всех предсказываемых переменных энтити. Затем в процессе игры можно увидеть какие из этих переменных не попадают в предсказание. Переменные отмечаются красным цветом когда клиент не предсказывает ее значение. Решение проблем
Предположим мы видим переменную красным цветом в панели cl_pdump время от вермени. Теперь, мы знаем что иногда клиент производит отличающеся значение от того что на сервереs. Обычно это можно отнести к следующим проблемам:
2 Подробности
2.1 Передача по сети через таблицы данных
2.2 Создание таблицы предсказаний
2.1 Консольные комманды
2.1.1 cl_predictionlist
2.1.2 cl_pdump
3 Решение проблем
Вступление
Система предсказания (prediction) Source спроектирована с целью уменьшить влияние задержек на динамику игры. Наиболее чувтсвительны к задержкам события когда игрок нажимает клавиши (во время чего комманда отправляется на сервер и возвращается обратно), система предсказания Source имитирует эффект нажатия кнопки на клиенте немедленно. Когда после этого приходит ответ от сервера, клиент определяет корректная или нет спекулятивная имитация.
- 99% времени, спекуляция клиента корректная. Поэтому, клиент может играть не замечая задержек в передаче по сети.
- Если спекуляция клиента не корректная, клиент возвратно повторяет симуляцию всех комманд которые выполнялись с ошибочными данными. В связи с этим, клиент ощущает небольшой рывок в его
позиции видимости, анимации оружия,
и т.д. К счастью, если код написан корректно, этот случай не очень часто встречается.
Основные требования которые требуется выполнить для того чтоб энтитя использовала систему предсказания:
- Одинаковые части кода энтити должны выполняться на клиенте и сервере. Такой код относится к общему коду (shared code).
- Все переменные энтити которые меняются на сервере и клиенте должны передаваться при помощи таблиц данных.
- Эти переменные должны также быть добавлены в список называемый таблица предсказаний (prediction table).
Хорошее место для начала — рассмотреть пример кода оружия. Откройте файл src/game_shared/basecombatweapon_shared.cpp. Блоки #ifdef CLIENT_DLL и #ifdef GAME_DLL являются разделением кода между клиентским и сервером (условные директивы компилятора). Эти блоки указывают какой код компилируется для client DLL а какой для server DLL. Приведенный ниже код (сокращенный) соответствует шагу 2 описанной выше последовательности (помещает переменные измененные общим кодом в таблицу данных).
BEGIN_NETWORK_TABLE (CBaseCombatWeapon, DT_BaseCombatWeapon)Создание таблицы предсказаний
#if !defined (CLIENT_DLL)
SendPropInt (SENDINFO (m_iState), 8, SPROP_UNSIGNED),
SendPropEHandle (SENDINFO (m_hOwner)),
#else
RecvPropInt (RECVINFO (m_iState)),
RecvPropEHandle (RECVINFO (m_hOwner)),
#endif
END_NETWORK_TABLE ()
Таблица предсказаний описывает данные в вашей энтити которые должны быть одинаковые на клиенте и сервере когда клиент спекулятивно имитирует комманду. Это список переменных котрые передаются по сети и их типы. Если значение допустимое к отклонению от серверного (как в случае с значением с плавающе запятой которое передается с урезанным количеством бит), то вы можите указать на сколько допустимо отклонение. В коде приведенном ниже, это выполняется макросом DEFINE_PRED_FIELD_TOL macro.
Примечание: таблица предсказаний только требуется к наличии в client DLL, так что ограничте код при помощи #ifdef CLIENT_DLL.
#ifdef CLIENT_DLLКонсольные комманды
BEGIN_PREDICTION_DATA (CBaseCombatWeapon)
DEFINE_PRED_FIELD (m_nNextThinkTick, FIELD_INTEGER, FTYPEDESC_INSENDTABLE),
DEFINE_PRED_FIELD (m_hOwner, FIELD_EHANDLE, FTYPEDESC_INSENDTABLE),
DEFINE_PRED_FIELD_TOL (m_flNextPrimaryAttack, FIELD_FLOAT, FTYPEDESC_INSENDTABLE, TD_MSECTOLERANCE),
END_PREDICTION_DATA ()
#endif
Если вы добавляете функциональность к оружию и забываете выполнить шаги описанные выше, энтитя может сопровождаться рывками и страностями с анимацией. Ниже приводятся консольные комманды которые можно использовать для отладки в таких случаях. cl_predictionlist
Если ввести cl_predictionlist 1 в консоли, вы увидите графическое окно в верхнем правом углу. Оно отображает все энтити которые в данный момент используются системой предсказания Source (то есть: выполняющиеся одновременно на клиенте и сервере). левая колонка отображает индекс кажой энтити, средняя колонка отображает имя классов энтитей.
Как только будет определен индекс энтити, которую требуется отладить, используется cl_pdump. cl_pdump
Если установить значение cl_pdump к индексу предсказываемой энтити (из левой колонки в выводе окна cl_predictionlist), развернется обширный список всех предсказываемых переменных энтити. Затем в процессе игры можно увидеть какие из этих переменных не попадают в предсказание. Переменные отмечаются красным цветом когда клиент не предсказывает ее значение. Решение проблем
Предположим мы видим переменную красным цветом в панели cl_pdump время от вермени. Теперь, мы знаем что иногда клиент производит отличающеся значение от того что на сервереs. Обычно это можно отнести к следующим проблемам:
- Клиент не выполняет тот же код ч товыполняет сервер. Это может быть случай, если участок кода помещен в секцию ограниченную #ifdef GAME_DLL или #ifndef CLIENT_DLL вокруг кода который влияет на переменную отмеченную красным цветом.
- Другая переменная которая влияет на данное значение становящееся красным не передается через таблицу данных. В таком случае на клиенте, значение этой переменной всегда неверное (так как сервер никогда не передает его).
- Также возможно не было добавлено соответствующее отклонение при помощи макроса DEFINE_PRED_FIELD_TOL. Например, если передается значение с плавающей запятой в диапазоне от 0.0 до 255.0, и было задано только 4 бита точности, тогда требуется отклонение около 17.0, иначе система предсказания считает значение переменной неверным изза того что значение сжимается до 4 бит перед отпарвкой клиенту.