Маппинг и SDK

KF SDK: зоны, туман, небо и освещение

Это два урока маппера K-2 с форума killingfloor.ru (2011-2012): «KF SDK: Зоны» и «KF SDK: Освещение». Основы работы в редакторе есть в основах редактора карт и в руководстве по маппингу, а связь тумана с дистанцией отсечения разобрана в статье CullDistance и туман расстояния.

Что такое зоны

Зоны — это части игрового пространства, на которые карта делится при компиляции. Каждой зоне в редакторе можно задать свои параметры.

Чтобы увидеть зоны, переключите окно редактора в режим Zone/Portal (Alt+2): каждая зона подсвечивается своим цветом.

Как образуются зоны:

  1. Любое вырезанное (Subtract) пространство образует зону.
  2. Если одно Non-solid пространство касается другого или пересекается с ним, они образуют одну зону.
  3. Если Non-solid пространства не касаются друг друга, это разные зоны.

Как разделить зону порталом

Зону можно разрезать и вручную:

  1. Создайте плоский браш кнопкой Sheet. Размер не важен, главное, чтобы он полностью перекрывал зону в нужном месте.
  2. Поставьте его туда, где должна пройти граница.
  3. Нажмите Add Special Brush и в появившемся окне отметьте Portal, Invisible и Two Sided: перегородка будет неосязаемой, невидимой и двухсторонней. В редакторе такой браш обводится зелёным контуром.
  4. Скомпилируйте карту: после этого зона будет разделена.

Если перегородки мешают обзору, включите во вьюпорте Realtime Preview (клавиша P), и они станут невидимыми.

Чтобы удалить портал, выделяйте не поверхность, а сам браш, который за неё отвечает: у Zone/Portal это, как правило, зелёный каркас на 2D-видах. Тогда он удаляется клавишей Delete (уточнение K-2 из комментариев).

Настройка зон: ZoneInfo

Свойства зоне задаёт актор ZoneInfo (Actors → Info → ZoneInfo): поставьте его внутрь зоны и отредактируйте свойства. На одну зону — один ZoneInfo: если поставить в зону несколько, настройки могут работать некорректно. Через ZoneInfo можно добавить туман, полностью осветить зону и дать ей название.

Вкладка ZoneInfo:

СвойствоЧто делает
bClearToFogColorЕсли включён туман, скрытое им пространство окрашивается в цвет тумана
bDistanceFogTrue включает туман (туман повышает производительность)
bSoftKillZВключает эффект KillZ: игрок погибает, если упадёт или поднимется на заданное расстояние по вертикали
bTerrainZoneОбязательная опция, чтобы в зоне работал ландшафт
KillZСамо расстояние KillZ
LocationNameНазвание локации (в KF видно только в командном чате)
ZoneTagТег зоны для ZoneTrigger-ов (в KF ни опция, ни ZoneTrigger-ы не актуальны)

Вкладка ZoneLight:

СвойствоЧто делает
AmbientBrightness / AmbientHue / AmbientSaturationДополнительное статическое освещение всей зоны. Выглядит не очень красиво и используется редко
bNewKFColorCorrectionВключает коррекцию цвета при включённом тумане, цвет задаётся в KFOverlayColor (используется, например, на KF-Wyre). Возможность добавила Tripwire Interactive в одном из патчей, и иногда она работает неправильно или не работает вовсе
bNoKFColorCorrectionНе использовать коррекцию цвета
DistanceFogBlendTimeЧерез сколько секунд вошедший в зону игрок увидит туман
DistanceFogColorЦвет тумана
DistanceFogEndРасстояние от игрока, дальше которого в тумане ничего не видно
DistanceFogEndMinАльтернатива DistanceFogEnd для игр, где в настройках есть дальность видимости в тумане (KF к ним не относится); служит для оптимизации
DistanceFogStartРасстояние от игрока, на котором начинается туман. Отрицательное значение делает туман гуще

Остальные опции (кроме KFOverlayColor) лучше оставить по умолчанию. Как подобрать начало и конец тумана под CullDistance, описано в статье CullDistance и туман расстояния.

Небо: зона SkyZoneInfo

  1. Создайте для неба отдельную зону — обычно это куб, вырезанный за пределами карты.
  2. Поставьте внутрь SkyZoneInfo (Actors → Info → ZoneInfo → SkyZoneInfo). Он служит постоянной «камерой», через которую игрок видит небо. Свойства те же, что у ZoneInfo, но у SkyZoneInfo есть направление (показано стрелкой).
  3. Чтобы небо не было чёрным, задайте в свойствах зоны AmbientBrightness или включите для окружения опцию Unlit.
  4. Оформите скайбокс. Проще всего наложить текстуры неба на стенки куба. Можно сделать и сложнее: в скайбокс можно поставить почти что угодно (чаще всего статики), и всё это будет видно. Часто используют купол неба (Skydome) с декорациями, а анимированными текстурами делают движение облаков или молнии. Хорошие примеры — скайбоксы официальных карт KF-Suburbia, KF-Departed и KF-Wyre.
  5. Укажите, за какими поверхностями показывать небо. Например, если карта построена внутри огромного куба, выделите его грани, которые должны стать «прозрачными», и в свойствах поверхностей отметьте Fake Backdrop.
  6. Проверьте результат, включив показ бэкдропа в настройках View окна редактора (клавиша K).

Если в игре на отдельных участках карты видны размазанные «следы» текстур, так выглядит пространство за бэкдропом без скайбокса: проверьте, не отмечен ли Fake Backdrop у поверхностей, где неба быть не должно. У автора темы причиной оказался незакрытый шов в геометрии: после того как дыру закрыли, эффект пропал (K-2 и Mysterion, тема «Баг на карте с текстурами», форум killingfloor.ru).

Где взять текстуры неба и какого размера делать куб, рассказано в статье фоновые звуки, снег, телепорты и текстуры неба.

Освещение: с чего начать

Освещение — одна из важнейших частей дизайна карты. При хорошем свете скромная детализация почти незаметна, а отличную геометрию легко испортить плохим светом или Ambient-яркостью.

  • Для работы со светом есть режимы вьюпорта Lighting Only (Alt+0) и Dynamic Light (Alt+5). Первый показывает освещение «в чистом виде» и является основным, во втором свет наложен на текстуры геометрии и объектов — он для доводки и полного предпросмотра.
  • После добавления или изменения источников освещение надо скомпилировать. Кроме полного билда карты есть две отдельные кнопки: Build Lighting пересобирает всё освещение, Build Changed Lighting — только источники, изменённые с прошлой компиляции. Второй вариант экономит время, но игнорирует, например, изменение размера и формата карт освещения.
  • Нескомпилированный свет считается динамическим и обычно не соответствует итоговому: он проходит сквозь объекты без теней, не учитываются углы падения и соседние источники.

K-2 делит освещение на три условные категории:

КатегорияКак устроеноЗачем
ФоновоеСвет без видимого источника: группы обычных Light-ов одинакового или близкого оттенка и насыщенности, со средним радиусом (12-32), почти равномерно распределённые по участкуРовно осветить место без естественных источников или «расширить» их действие, имитируя рассеянный свет. Наложение похожих источников даёт много оттенков разной яркости и выглядит гораздо лучше фоновой яркости зоны
ЕстественноеСвет, который игрок связывает с видимым источником; тип любой, в том числе комбинированный, радиус зависит от карты и источникаСвет фонарей, фар, огня; сюда же относится солнечный или лунный свет под скайбокс
ДополнительноеВ основном Light-ы с малым радиусом (2-8) и, при желании, высокой яркостьюВместе с другими источниками подсветить детали и места, куда другой свет не достаёт, или подчеркнуть какие-то особенности

Свойства Light

Light — обычная «лампочка», корень всех остальных типов света. Добавляется через ПКМ → Add Light Here, в браузере акторов лежит в Actor → Light.

Вкладка Light Color:

СвойствоЧто делает
LightBrightness / LightHue / LightSaturationЯркость, оттенок и насыщенность (кроме света, меняют и цвет иконки)

Если щёлкнуть по вкладке Light Color, появятся две кнопки: взять цвет пипеткой или выбрать его на палитре. Внимание: если выделить сразу несколько источников с разными настройками, открытие палитры роняет редактор.

Вкладка Lighting:

СвойствоЧто делает
bActorShadowsОтбрасывают ли акторы тени (на практике ни на что не влияет)
bAttenByLifeТеоретически — ослабление света со временем жизни
bCoronaВключает корону (см. ниже)
bDirectionalCoronaРазмер короны зависит от угла взгляда: максимальна при взгляде прямо и «исчезает» под углом 90 градусов
bDynamicLightДелает свет динамическим: он проходит сквозь объекты без теней (часто выглядит неестественно), зато не требует компиляции и годится для некоторых эффектов
bLightingVisibilityСчитать ли видимость освещения от этого источника при проверке карты
bSpecialLitЕсли True, свет виден только на поверхностях BSP-брашей с отмеченной галочкой Special Lit
LightConeУгол конуса света (только при LE_Spotlight); максимум 255 соответствует примерно 160 градусам
LightEffectОсобый эффект освещения (не все работают корректно)
LightPeriod / LightPhaseТеоретически отвечают за анимацию эффектов, но K-2 не нашёл в стандартном наборе эффекта, на который они влияли бы
LightRadiusРадиус освещения в собственных единицах: одна единица — примерно 27 UU. Реальные границы видны, если включить отображение акторов Radii View
LightTypeТип освещения (дополнительный эффект), работает и вместе с LightEffect, и отдельно; большинству типов нужен bDynamicLight = True

Если на карте слишком ярко, уменьшите LightBrightness или LightRadius у источников (совет UltraKill из комментариев).

Типы источников света

Spotlight (Actor → Light → Spotlight). Направленный свет, светит конусом. По сути это обычный Light с LightEffect = LE_Spotlight, но со стрелкой направления, что упрощает настройку.

Sunlight (Actors → Light → Sunlight). Солнечный свет. От обычного Light отличается иконкой, стрелкой направления и установленным по умолчанию LE_Sunlight. Он покрывает всю территорию карты, куда может попасть. Где бы ни стоял Sunlight, источником света всегда служит пространство за бэкдропом, поэтому «небо» обязательно.

В Unreal Engine 2 нет рассеивания света как такового: солнечный свет тут как на Луне, и если Sunlight — единственный источник, всё в тени остаётся чёрным. Частично это решают дополнительные источники, в том числе дополнительные Sunlight-ы: основной Sunlight плюс несколько слабее и без оттенка, с тем же общим углом падения лучей, дают близкий к реалистичному свет на открытых пространствах. Их количество и свойства зависят от карты, и это требует возни с вкладкой Movement, точной настройки Rotation по трём осям и некоторых расчётов. Альтернатива — фоновое освещение мест в тени.

TriggerLight (Actor → Light → TriggerLight). Свет, который включается и выключается по схеме Event → Tag: в свойствах света на вкладке Events пишется тег в поле Tag, у триггера тот же тег — в поле Event. По умолчанию динамический. Для правильной работы нужно настроить InitialState:

InitialStateПоведение
TriggerTurnsOnПри активации свет включается и остаётся включённым
TriggerTurnsOffПри активации свет выключается и остаётся выключенным
TriggerToggleКаждая активация включает или выключает свет, сколько угодно раз
TriggerControlТолько для обычных Trigger-ов: свет горит, пока Trigger активирован, и наоборот
TriggerPoundТеоретически свет должен плавно включаться и выключаться в течение RemainOnTime, на практике работает как разовый on/off

Прочие свойства TriggerLight:

СвойствоЧто делает
bDelayFullOnДелает включение и выключение плавным, игнорируя ChangeTime
bInitiallyOnВключён ли свет изначально
ChangeTimeЗа сколько времени яркость нарастает от 0 до заданной при включении (и наоборот при выключении)
RemainOnTimeТеоретически параметр только для TriggerPound, на практике эффекта нет

KFMovableLight (Actor → Light → KFMovableLight). Свет, который можно привязать к муверу, чтобы он двигался вместе с ним:

  1. На вкладке Lighting вручную поставьте bDynamicLight = True.
  2. На вкладке Movement впишите тег в поле AttachTag.
  3. Муверу, к которому привязываете свет, впишите тот же тег в поле Tag (вкладка Events).

Когда мувер движется, свет повторяет то же движение относительно своей исходной позиции.

Effect_TacLightGlow и HeadlightCorona K-2 пропустил как неактуальные.

Короны

Короны света — одна из самых простых и при этом красивых декораций. По сути это видимые «скины» лампочек: спрайты с (как правило) полупрозрачной текстурой.

  1. В свойствах источника на вкладке Lighting поставьте bCorona = True.
  2. На вкладке Display задайте Skin: выберите текстуру в браузере и нажмите Use или впишите путь вручную.
СвойствоЧто делает
CoronaRotationКоэффициент вращения короны в зависимости от расстояния от игрока до источника
CoronaRotationOffsetНачальный поворот короны
MaxCoronaSize / MinCoronaSizeМаксимальный и минимальный размер короны
UseOwnFinalBlendПредположительно: используется ли сложная текстура FinalBlend

K-2 советует делать для корон отдельные источники с нулевой яркостью и большим радиусом.

Тени и разрешение карт освещения

Качество теней прежде всего зависит от разрешения карт освещения, но это касается только BSP-геометрии.

  1. Выделите нужные поверхности BSP-брашей и откройте их свойства.
  2. Измените параметр Light map: от 256 до 1, по умолчанию 16.0. Чем меньше значение, тем выше разрешение (максимум — 1.0).

Высокое разрешение увеличивает вес карты, время компиляции и немного бьёт по производительности, поэтому 1.0-2.0 имеет смысл ставить только там, где это заметнее всего. Исключение — маленькие ненагруженные карты: на них можно сразу нажать Shift+S и выставить максимальное качество.

На полигональные модели и ландшафт свет ложится иначе (vertex lit): чем больше полигонов у модели и чем они мельче, тем лучше свет и тени (то же с сеткой ландшафта). Но до максимального качества теней на BSP всё равно далеко. Отдельные тени можно сделать Projector-ами (Actor → Projector) — они выглядят как надо на любых объектах. Главная сложность — нарисовать текстуру, ведь проектор просто проецирует её.

Формат карт освещения

Формат освещения выбирается в Build Options (параметры компиляции). Вариантов три:

ФорматСжатие
DXT1Максимальное
DXT3Среднее (используется по умолчанию)
RGB8Без сжатия

С RGB8 освещение заметно качественнее и мягче, пропадает эффект «цветных пятен». Несжатый формат увеличивает вес карты и снижает производительность, но не так сильно, как высокое разрешение карт освещения.

Сравнивая комбинации (DXT3 или RGB8, Light map 16.0 или 1.0-2.0), K-2 пришёл к выводу: при невысоком разрешении RGB8 выглядит гораздо лучше DXT3, а при высоком разница становится очень небольшой. Искажения от сжатия намного заметнее на цветном свете, чем на белом. Подбирайте комбинацию, исходя из производительности карты.

Яркость и оттенок карты

Частая проблема: в игре яркость и общая гамма карты не совпадают с тем, что видно в редакторе, — как правило, карта получается слишком яркой. Цвет можно скорректировать в свойствах ZoneInfo для одной зоны или в Level Properties (F6) сразу для всей карты:

  1. На вкладке ZoneInfo поставьте bDistanceFog = True.
  2. На вкладке ZoneLight поставьте bNewKFColorCorrection = True.
  3. Отрегулируйте гамму в KFOverlayColor. Если равномерно уменьшить все три канала B, G и R (синий, зелёный, красный), общая яркость карты снизится.

Туман обязателен для работы цветокоррекции. Если он не нужен, задайте ему запредельный радиус.

Мигалка и фары: разбор с KF-MountainPass

Из ответа K-2 в теме «Вопросы, вопросы и еще раз вопросы.» на форуме killingfloor.ru. Мигалка и фары полицейской машины на KF-MountainPass собраны из множества небольших компонентов, и лучший способ их изучить — открыть карту и посмотреть.

  • Мигалка: 4 обычных Light-а, которые дают постоянный свет; 2 TriggerLight-а с LightType=LT_Blink и bInitiallyOn=True (bInitiallyOn — вторая строчка нижней вкладки TriggerLight); 2 спрайт-Emitter-а, генерирующие частицы вспышек.
  • Фары: Light-ы с нулевой яркостью и коронами; Light с малым радиусом и большой яркостью, освещающий статик на месте фар; обычные Light-ы с умеренным радиусом и яркостью, освещающие окружение.

Если свет в одной комнате освещает только стены, а в других комнатах всё в порядке, K-2 советовал проверить, освещается ли потолок, какой у источников радиус, не отмечен ли у поверхностей пола Special Lit и не шейдер ли на полу. В теме «Проблема с освещением» это оказался баг, который лечится радиусом освещения от 16 до 32 или небольшим перемещением источников.