Ru/Physics Entities on Server & Client

=Обзор=
Основным преимуществом движка Source является физическая имитация твердых тел. Эта имитация реализует основную механику и физику Ньютона такие как гравитация, траектория, трение, столкновения, прыжки и плавание. Модели поддерживают эту имитация предоставляя информацию о их модели коллизий, типе материалов, весе и т.д. В режиме однопользовательской игры все физические энтити контроллируются и имитируются сервером (физика на стороне сервера) и передаются клиенту. В режиме многопользовательской игры мелкие объекты подобные консервным банкам или бутылкам которые не влияют на геймплей, полностью имитируются на стороне клиента и поэтому не синхронизируется между клиентами. Это необходимо в связи с тем что движение физических энтитей создает значительный сетевой траффик с того момента как они изменяют их позицию и базовое направление в каждом кадре. Сообщение по сети этих изменений может почти полностью блокировать любое соединение как только начнут двигаться множество физизических объектов в одно время (взрывы и т.д.). Физ-ие объекты на стороне клиента не влияют на передвижение игрока и они всегда должны быть гораздо меньше чем сам игрок, так что игрок не может спрятаться за ними. Во время разрушения серверных бьющихся объектов, они разбиваются на меньшие фрагменты имитирующиеся на стороне клиента.
=Добавление физических энтитей=
Для маппера довольно просто помещать физические энтити в Хаммере. Для однопользовательских карт класс энтити physics_prop должен быть использован для создания контроллируемых серверной стороной энтитей. Игрок выполняет корректную коллизию с этими энтитями, может проходить сквозь них, двигать их с разных сторон или поднимать их. К сожалению этот класс не может использоваться в многопользовательской игре так как взаимодействие игрока с физическими энтитями не предсказывается на стороне клиента и может вызвать неестественное или задержанное движение. Поэтому должен быть использован специальный класс энтити prop_physics_multiplayer, который реализует более упрощенное поведение коллизии (COLLISION_GROUP_PUSHAWAY). Многопользовательские физ-ие энтити только могут толкаться, но нельзя ходить сквозь них или поднимать их. Если они больше, игрок просто отталкивается. Становятся ли многопользовательские физ-ие энтити серверными или имитируются на стороне клиента, определяется в объекте модели.
Физические свойства модели определяются в её .QC файле с помощью 3 секций: $surfaceprop, $collisionmodel, $keyvalues. Первая секция $surfaceprop устанавливает свойства поверхности модели как описано в текстовом файле \scripts\surfaceproperties.txt. Тут описываются свойства типа трения, эластичности и звука коллизий. Следующая секция $collisionmodel устанавливает модель коллизий и вес объекта. Для простмотра модели коллизий для энтитей в игре включите консольную переменную "vcollide_wireframe 1". Третья секция "prop_data" включенная в $keyvalues. Здесь описываются свойства объекта например кол-во здоровья, разбиваемость модели и физический режим описанные в (). Ниже приводится пример:
$surfaceprop "cardboard" // свойства поверхности объекта
$collisionmodel "mymodel.smd" {
 $Mass 40	// Масса в килограммах
 $concave
}
$keyvalues
{
	"prop_data"
	{
		"base" 		"Cardboard.Medium" // базовый материал определенный в propdata.txt
		"health"		"40" // перезапись свойств материала
		"physicsmode"	"1" // устанока произвольного режима физики
	}
}
Режим физики определяется если объект является серверной или клиентской физической энтитей. Существует 2 серверных режима и один клиентский, описаны они в props_shared.h:
#define PHYSICS_MULTIPLAYER_AUTODETECT	0	// режим автоопределения основанный на массе и размере
#define PHYSICS_MULTIPLAYER_SOLID		1	// серверный, монолитный (сталкивается с игроком)
#define PHYSICS_MULTIPLAYER_NON_SOLID	2	// серверный, не монолитный
#define PHYSICS_MULTIPLAYER_CLIENTSIDE	3	// клиентский, не монолитный
Если свойство физического режима не установлено в propdata.txt или в QC file, режим физики может быть получен из функции GetAutoMultiplayerPhysicsMode() основанный на размере и весе модели. Модель становиться клиентской физ-ой энтитей, если её размер меньше определенной границы (устанавливается консольной переменной sv_pushaway_clientside_size</code>).
=Группы коллизий=
По нескольким причинам нет необходимости чтоб все динамические физ-ие энтити вызывали коллизии между собой. Это может быть по разным причинам геймплея, но чаще это делается по причине производительности. Особенно создание множества мелких, быстро движущихся кусков осколков которые могут значительно снизить производительность. Для визуального эффекта бющихся осколков или взрывающихся подобных частицам объектов достаточно их коллизии с статическими предметами мира, но не самих с собой или других динамических объектов. Для реализации специального поведения коллизий движок Source позволяет определять группы коллизий и указывать если элементы этих групп сталкиваться или нет. Каждая энтитя принадлежит только одной группе одновременно, устанавливается это функцией SetCollisionGroup(). Новые группы и новые правила могут быть легко добавлены. Подсистемы физики запрашивают виртуальную функцию bool CGameRules::ShouldCollide(int group0, int group1) чтобы для определения должна ли вызываться проверка коллизии между двумя объектами.
Изначально определены группы:
COLLISION_GROUP_NONE 	По умолчанию, сталкивается с статическими и динамическими объектами
COLLISION_GROUP_DEBRIS 	Сталкивается только с миром и статическими вещами
COLLISION_GROUP_DEBRIS_TRIGGER 	Тоже что и предыдущее, но переключает триггеры
COLLISION_GROUP_INTERACTIVE_DEBRIS	Сталкивается со всем за исключением других осколков или интерактивных осколков
COLLISION_GROUP_INTERACTIVE 	Сталкивается со всем за исключением осколков или интерактивных осколков
COLLISION_GROUP_PLAYER 	Группа коллизий игрока
COLLISION_GROUP_BREAKABLE_GLASS 	Специальная группа для стеклянных осколков
COLLISION_GROUP_VEHICLE 	Группа коллизии для управляемого транспорта
COLLISION_GROUP_PLAYER_MOVEMENT 	Для однопользовательского режима то же чо Collision_Group_Player, для многопользовательского - это отфильтровывает других игроков и CBaseObjects
COLLISION_GROUP_NPC 	Базовая группа NPC
COLLISION_GROUP_IN_VEHICLE 	Любая энтить внутри транспорта
COLLISION_GROUP_WEAPON 	Для любого огружия требующего определения коллизий
COLLISION_GROUP_VEHICLE_CLIP 	Клип браш для транспорта, для ограничения движения транспорта
COLLISION_GROUP_PROJECTILE 	Пули
COLLISION_GROUP_DOOR_BLOCKER 	Блокировка энтитей не допустимых к движению рядом с дверями
COLLISION_GROUP_PASSABLE_DOOR 	Двери с которыми не может сталкиваться игрок
COLLISION_GROUP_DISSOLVING 	Вещи проникают друг в друга
COLLISION_GROUP_PUSHAWAY 	Немонолитные на стороне клиента и сервера, отталкивают игрока
=Дополнение=
Список допустимых комманд в секции $collisionmodel модели:
$mass 	Установка массы модели вручную
$automass 	Указывает физической системе вычислять массу для модели, основанную на её свойствах поверхности и размерах
$inertia 	Инерциальная величина
$damping 	Линейное торможение
$rotdamping 	Вращательное торможение
$drag 	Изменяет плотность (сопротивление) воздуха
$concave 	Физ-ая модель коллизий не одна выпуклая оболочка. Если это не установлено, создается одна сплошная выпуклая оболочка вокруг данной геометрии.
$masscenter 	Переопределяет центр масс в локальных координатах
$jointskip 	Редко используется. Исключает джоинт в модели коллизий из использования. (например если используется рендеринг модели тряпичной куклы, и в ней есть кости которые не нужны)
$jointmerge 	Соединяет прикрепление вертексов для двух джоинтов.
$rootbone 	Наиболее главная кость обладающая коллизией.
$jointconstrain 	Ограничения движения джоинтов
$jointinertia 	Подобно $inertia, но отдельно для кости
$jointdamping 	Подобно $damping, но отдельно для кости
$jointrotdamping 	Подобно $rotdamping, но отдельно для кости
$jointmassbias 	Масса автоматически распространяется в объеме, это позволяет сместить ее к костям
$noselfcollisions	Отключить все коллизии между костями в данной модели, обычно для производительности
$jointcollide 	Если указаны какие-то из $jointcollide, только эти джоинты подвергаются коллизии между собой
$animatedfriction	Используется для анимирования значаения трения на джоинтах во времени.
Список доступных записей для определений в propdata.txt:
base 	Указывает базовый класс от которого происходит наследование (базовые типы перечисляются в propdata.txt)
blockLOS 	Переопределяет какая из опор может блокировать линию видимости для NPC
AIWalkable 	Переопределяет какой из AI примет эту опору как проходимую.
dmg.bullets 	Повреждения от пуль создаются на этой опоре.
dmg.club 	Повреждения от ударов создаются на этой опоре.
dmg.explosive 	Повреждения от взрывов создаются на этой опоре.
health 	Количество здоровья которое нужно убрать для разрушения.
explosive_damage	Эта опора создает взрывное повреждение.
explosive_radius	Радиус взрыва создаваемый этой опорой когда она разрушается.
breakable_model 	Тип разбиваемых осколков на которые может развалиться эта опора
breakable_count 	Число осколков на которе распадается эта опора.
allowstatic 	Позволяет этой опоре быть статической или физически имитируемой.
physicsmode 	Устанавливает поведение сетевой физики (1 - полная, 2 - не монолитная, 3 - на стороне клиента)