Физические энтити на стороне клиента и сервера

Обзор

Основным преимуществом движка 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" // object surface properties

$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).

Группы коллизий

По нескольким определенным причинам нет необходимости чтоб все динамические физ. энтити вызывали коллизии между собой. Это может быть по разным причинам геймплея, но больше это результат производительности. Особенно создание множеством мелких, быстро движущихся кусков осколков могут значительно снизить производительность. Для визуального эффекта бющихся осколков или взрывающихся частице-подобных объектов достаточно их коллизии с статическими предметами мира, но не самих с собой или других динамических объектов. Для имплементации специального поведения коллизий движок 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

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

$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 — на стороне клиента)

Автор: DarkLight.
26 января 2005, 20:08