Unreal EngineSeniorSystem design

Как упаковать (package) и развернуть игру на Unreal Engine для разных платформ?

Packaging использует UAT (UnrealAutomationTool) с командой BuildCookRun, которая компилирует код, кукает ассеты в .pak файлы и стейджит результат. Deployment зависит от платформы: Steam, консольные devkits или ручной деплой бинарников.

Packaging и деплой игры на Unreal Engine

Архитектура пайплайна упаковки

Packaging в Unreal состоит из четырёх стадий: Build (компиляция C++), Cook (конвертация ассетов в платформо-специфичные форматы), Stage (копирование в staging directory) и Pak (упаковка в .pak архивы с опциональным шифрованием).

Базовая команда упаковки через UAT

#!/bin/bash
UE_ROOT="/opt/unreal-engine-5.3"
PROJECT="/workspace/MyGame/MyGame.uproject"
OUTPUT="/output/builds"

# Windows (Shipping)
"$UE_ROOT/Engine/Build/BatchFiles/RunUAT.bat" BuildCookRun \
  -project="$PROJECT" \
  -platform=Win64 \
  -clientconfig=Shipping \
  -serverconfig=Shipping \
  -cook \
  -build \
  -stage \
  -pak \
  -archive \
  -archivedirectory="$OUTPUT/Win64"

# Linux (Dedicated Server)
"$UE_ROOT/Engine/Build/BatchFiles/RunUAT.sh" BuildCookRun \
  -project="$PROJECT" \
  -platform=Linux \
  -clientconfig=Shipping \
  -serverconfig=Shipping \
  -cook \
  -build \
  -stage \
  -pak \
  -server \
  -noclient \
  -archive \
  -archivedirectory="$OUTPUT/LinuxServer"

# Mobile (Android)
"$UE_ROOT/Engine/Build/BatchFiles/RunUAT.sh" BuildCookRun \
  -project="$PROJECT" \
  -platform=Android \
  -clientconfig=Shipping \
  -cookflavor=ETC2 \
  -cook -build -stage -pak -archive \
  -archivedirectory="$OUTPUT/Android"

Конфигурация таргетов

# MyGame/Source/MyGame.Target.cs — контролирует тип сборки
# MyGame/Source/MyGameServer.Target.cs — серверный таргет

# Пример Target.cs для Shipping:
# using UnrealBuildTool;
# public class MyGameTarget : TargetRules
# {
#   public MyGameTarget(TargetInfo Target) : base(Target)
#   {
#     Type = TargetType.Game;
#     DefaultBuildSettings = BuildSettingsVersion.V5;
#     bUsesSteam = true;
#   }
# }

Шифрование pak-файлов

# Config/DefaultCrypto.json
# {
#   "EncryptionKey": {
#     "Name": "MyGame",
#     "Guid": "00000000-0000-0000-0000-000000000000",
#     "Key": "base64-encoded-32-byte-aes-key-here"
#   },
#   "bEnablePakSigning": true,
#   "bEnablePakIndexEncryption": true,
#   "bEnablePakEntryEncryption": true
# }

# Генерация ключа:
dd if=/dev/urandom bs=32 count=1 2>/dev/null | base64

Деплой в Steam

# steamworks_sdk/tools/ContentBuilder/builder_linux/steamcmd
cat > /tmp/steam_build.vdf <<'EOF'
"AppBuild"
{
  "AppID" "1234567"
  "Desc" "CI build $(git rev-parse --short HEAD)"
  "BuildOutput" "/output/steam"
  "Depots"
  {
    "1234568"
    {
      "FileMapping"
      {
        "LocalPath" "/output/builds/Win64/WindowsNoEditor/*"
        "DepotPath" "."
        "recursive" "1"
      }
    }
  }
}
EOF

steamcmd \
  +login "$STEAM_USERNAME" "$STEAM_PASSWORD" \
  +run_app_build /tmp/steam_build.vdf \
  +quit

Деплой dedicated server (Linux)

# Загружаем на сервер через rsync
rsync -avz --delete \
  /output/builds/LinuxServer/MyGameServer/ \
  deploy@gameserver:/opt/mygame/

# Systemd unit для автозапуска
sudo tee /etc/systemd/system/mygame.service <<'EOF'
[Unit]
Description=MyGame Dedicated Server
After=network.target

[Service]
User=gameserver
WorkingDirectory=/opt/mygame
ExecStart=/opt/mygame/MyGameServer-Linux-Shipping \
  /Game/Maps/MainMap \
  -port=7777 \
  -QueryPort=27015 \
  -log \
  -NOSTEAM
Restart=on-failure
RestartSec=5

[Install]
WantedBy=multi-user.target
EOF

sudo systemctl enable --now mygame

CI/CD пайплайн (GitHub Actions)

name: Package and Deploy
on:
  push:
    branches: [release/*]

jobs:
  package:
    runs-on: [self-hosted, linux, unreal]
    steps:
      - uses: actions/checkout@v4
        with:
          lfs: true

      - name: Cook and Package
        run: |
          /opt/ue5.3/Engine/Build/BatchFiles/RunUAT.sh BuildCookRun \
            -project=$GITHUB_WORKSPACE/MyGame.uproject \
            -platform=Linux \
            -clientconfig=Shipping \
            -cook -build -stage -pak -archive \
            -archivedirectory=/output/${{ github.sha }}

      - name: Deploy to Staging
        run: |
          rsync -avz /output/${{ github.sha }}/ \
            deploy@staging:/opt/mygame/
          ssh deploy@staging 'sudo systemctl restart mygame'

Подводные камни

  • Cook без общего DDC на CI занимает часы — настройте shared filesystem DDC или S3-compatible backend через UE-SharedDataCachePath env variable.
  • -cookflavor для Android должен включать ETC2 и ASTC — без этого на части устройств будут чёрные текстуры.
  • Shipping build по умолчанию включает bSplitIntoChunks для DLC — без явного отключения создаются лишние .pak файлы.
  • Ключ шифрования pak нельзя менять после релиза без патча клиента — храните его в секрете с самого начала (CI secrets, не в репозитории).
  • Linux dedicated server требует точное совпадение версии libc между build-машиной и prod-сервером — используйте Docker для сборки.
  • Steam upload занимает время даже если контент не изменился — всегда указывайте setlive отдельным шагом после верификации билда.
  • Консольные платформы (PS5/Xbox) требуют отдельного NDA, SDK и certified devkit — packaging pipeline значительно отличается от PC/Linux.
  • Версия EngineAssociation в .uproject должна точно совпадать с установленной версией на build-агентах — иначе UAT завершится с ошибкой поиска Engine.

Common mistakes

  • Объяснять packaging и deployment только по синтаксису, без жизненного цикла и стоимости.
  • Игнорировать ошибки, null/empty состояния, порядок инициализации или режим сборки.
  • Давать пример, который работает в демо, но ломается при изменении владельца ресурса.
  • Использовать макросы или specifier-и наугад и забывать про UObject GC.

What the interviewer is testing

  • Кандидат формулирует точную модель для packaging и deployment, а не только определение.
  • Пример компилируем, безопасен по lifetime и соответствует версии технологии.
  • Названы trade-off, ограничения и диагностируемые симптомы ошибки.
  • Понимает границу между C++ кодом, runtime/framework metadata и editor/UI слоем.

Sources

Related topics