Назад к блогу
Tutorial7 мин чтения

FiveM Экран создания персонажа: руководство по UI и скриптингу

Разработайте впечатляющий экран создания персонажа для FiveM. Управление лицом, одеждой, фоновыми сценами и лучшие бесплатные и премиальные конструкторы персонажей.

Agency Scripts

Основатель и ведущий разработчик Agency Scripts

Почему создание персонажа важно в ролевой игре

Создание персонажа , это первый интерактивный момент, который испытывает игрок на вашем FiveM ролевом сервере. Он задаёт тон всему последующему опыту. Отточенный, погружающий в атмосферу конструктор персонажей сообщает новым игрокам, что ваш сервер профессионально сделан и стоит их времени. Минимальный или багованный конструктор отправит их прямо в браузер серверов в поисках альтернатив. Помимо первого впечатления, конструктор персонажа определяет визуальную идентичность, которую каждый игрок несёт на протяжении всего ролевого опыта. Он задаёт наследственные черты, черты лица, причёски, одежду и биографические детали, такие как имя и дата рождения. Правильная реализация требует создания системы, которая взаимодействует с нативной системой внешности GTA V, предоставляет опции через интуитивный NUI интерфейс, сохраняет выборы в базу данных и надёжно загружает их каждый раз при появлении игрока.

Понимание системы внешнего вида пешеходов GTA V

В GTA V используется система внешности на основе наследия, где лицо персонажа смешивается из двух моделей родителей. Есть 46 возможных матерей и отцов, каждый с уникальной структурой лица. The SetPedHeadBlendData native контролирует смешивание, принимая значения формы и кожи от 0.0 до 1.0, определяющие, насколько персонаж похож на каждого из родителей. Помимо наследия, игра предлагает 20 категорий наложений через SetPedHeadOverlay охватывает такие особенности, как пятна, растительность на лице, брови, старение, макияж и повреждения кожи. Каждый оверлей имеет собственное значение прозрачности и может быть окрашен независимо с помощью SetPedHeadOverlayColor. Волосы обрабатываются отдельно через SetPedComponentVariation для модели и SetPedHairColor для цвета и выделений. Цвет глаз использует SetPedEyeColor со значениями от 0 до 31. Понимание этих natives важно, так как ваш NUI-интерфейс должен сопоставлять удобные для пользователя ползунки и селекторы с этими конкретными вызовами функций.

-- client/appearance.lua
function ApplyAppearance(ped, data)
    -- Heritage blend (mother, father, shape mix, skin mix)
    SetPedHeadBlendData(ped,
        data.mother, data.father, 0,
        data.mother, data.father, 0,
        data.shapeMix, data.skinMix, 0.0,
        false
    )

    -- Face features (-1.0 to 1.0 for each of 20 features)
    for i = 0, 19 do
        SetPedFaceFeature(ped, i, data.features[i] or 0.0)
    end

    -- Overlays (blemishes, beard, eyebrows, aging, makeup, etc.)
    for i = 0, 12 do
        local overlay = data.overlays[i] or {style = 0, opacity = 0.0}
        SetPedHeadOverlay(ped, i, overlay.style, overlay.opacity)
        if overlay.color then
            SetPedHeadOverlayColor(ped, i, overlay.colorType or 1,
                overlay.color, overlay.secondColor or overlay.color)
        end
    end

    -- Hair
    SetPedComponentVariation(ped, 2, data.hair or 0, 0, 2)
    SetPedHairColor(ped, data.hairColor or 0, data.hairHighlight or 0)

    -- Eye color
    SetPedEyeColor(ped, data.eyeColor or 0)
end

Создание NUI интерфейса

NUI (Natural User Interface) , это HTML, CSS и JavaScript-слой, с которым игроки взаимодействуют при создании персонажа. Хорошо продуманный конструктор персонажа делит процесс на логические этапы: сначала биографическая информация, затем выбор наследия, черты лица, наложения вроде бороды и макияжа, причёска и, наконец, одежда. Каждый этап должен показывать обновления в реальном времени на модели персонажа, чтобы игроки видели, как выглядят их выборы. Используйте вкладки или пошаговый интерфейс, чтобы игроки не были перегружены десятками опций сразу. Ползунки подходят для непрерывных значений, таких как смешение форм и черты лица, а сеточные селекторы с миниатюрами лучше для дискретных опций, например причёсок и одежды. Отправляйте каждое изменение в клиентский скрипт через fetch или систему сообщений NUI, чтобы обновление педа происходило мгновенно.

<!-- nui/index.html (simplified structure) -->
<div id="creator" class="creator-wrapper">
  <div class="steps-nav">
    <button data-step="bio" class="active">Identity</button>
    <button data-step="heritage">Heritage</button>
    <button data-step="features">Features</button>
    <button data-step="overlays">Appearance</button>
    <button data-step="hair">Hair</button>
    <button data-step="clothing">Clothing</button>
  </div>

  <div class="step-content" id="step-heritage">
    <label>Mother</label>
    <input type="range" id="mother" min="0" max="45" value="0">
    <label>Father</label>
    <input type="range" id="father" min="0" max="45" value="0">
    <label>Resemblance (Shape Mix)</label>
    <input type="range" id="shapeMix" min="0" max="100" value="50">
    <label>Skin Tone (Skin Mix)</label>
    <input type="range" id="skinMix" min="0" max="100" value="50">
  </div>
</div>

<script>
document.querySelectorAll('input[type="range"]').forEach(slider => {
  slider.addEventListener('input', () => {
    fetch('https://myresource/updateAppearance', {
      method: 'POST',
      body: JSON.stringify({
        type: slider.id,
        value: parseFloat(slider.value)
      })
    });
  });
});
</script>

Система камеры для предварительного просмотра персонажа

Выделенная система камер необходима для качественного опыта создания персонажа. Игрокам нужны крупные планы лица при настройке наследственных черт и наложений, средние планы для волос и верхней одежды, а также полный вид тела для штанов и обуви. Реализуйте контроллер камеры, который плавно интерполирует между предопределёнными позициями в зависимости от активного шага создания. Используйте CreateCam с DEFAULT_SCRIPTED_CAMERA type и RenderScriptCams для взятия контроля от игровой камеры. Для вращения разрешите игрокам перетаскивать мышь, чтобы вращаться вокруг персонажа, изменяя направление камеры при сохранении взгляда на педа. Ненавязчивая анимация покоя на педе, например WORLD_HUMAN_STAND_IMPATIENT сценарий, поддерживает естественный вид персонажа во время процесса создания, а не жёсткую позу T-pose.

-- client/camera.lua
local creatorCam = nil
local camAngle = 0.0

local CamPositions = {
    bio      = {offset = vector3(0.0, 0.9, 0.65), fov = 35.0},
    heritage = {offset = vector3(0.0, 0.7, 0.65), fov = 30.0},
    features = {offset = vector3(0.0, 0.5, 0.68), fov = 22.0},
    overlays = {offset = vector3(0.0, 0.5, 0.68), fov = 22.0},
    hair     = {offset = vector3(0.0, 0.6, 0.72), fov = 25.0},
    clothing = {offset = vector3(0.0, 2.2, 0.30), fov = 45.0},
}

function SetupCreatorCam(ped, step)
    local pos = CamPositions[step] or CamPositions.bio
    local pedCoords = GetEntityCoords(ped)
    local target = pedCoords + vector3(0.0, 0.0, pos.offset.z)

    if not creatorCam then
        creatorCam = CreateCam('DEFAULT_SCRIPTED_CAMERA', true)
        RenderScriptCams(true, true, 500, true, false)
    end

    local rad = math.rad(camAngle)
    local camPos = pedCoords + vector3(
        math.sin(rad) * pos.offset.y,
        math.cos(rad) * pos.offset.y,
        pos.offset.z
    )

    SetCamCoord(creatorCam, camPos.x, camPos.y, camPos.z)
    PointCamAtCoord(creatorCam, target.x, target.y, target.z)
    SetCamFov(creatorCam, pos.fov)
    SetCamActive(creatorCam, true)
end

Сохранение и загрузка данных персонажа

Все данные внешности персонажа должны сохраняться в базе данных, чтобы сохраняться при перезапусках сервера и загружаться при каждом появлении игрока. Структурируйте таблицу базы для хранения полной внешности в JSON вместе с биографическими полями: имя, фамилия, дата рождения, пол и национальность. После создания и подтверждения персонажа клиент отправляет полный объект данных на сервер, который проверяет диапазоны и вставляет в базу. При последующих входах сервер получает данные персонажа во время спавна и отправляет обратно клиенту, который вызывает тот же ApplyAppearance функция, используемая при создании. Для серверов с несколькими персонажами храните идентификатор слота персонажа, чтобы у каждого игрока могло быть несколько персонажей с независимыми внешностями.

-- server/database.lua
-- Using oxmysql for database operations
function SaveCharacter(playerId, charData)
    local identifier = GetPlayerIdentifier(playerId, 0)
    local appearance = json.encode(charData.appearance)

    MySQL.insert([[
        INSERT INTO characters
            (identifier, slot, firstname, lastname,
             dateofbirth, gender, nationality, appearance)
        VALUES (?, ?, ?, ?, ?, ?, ?, ?)
    ]], {
        identifier,
        charData.slot or 1,
        charData.firstname,
        charData.lastname,
        charData.dob,
        charData.gender,
        charData.nationality,
        appearance
    })
end

function LoadCharacter(playerId, slot)
    local identifier = GetPlayerIdentifier(playerId, 0)
    local result = MySQL.single.await([[
        SELECT * FROM characters
        WHERE identifier = ? AND slot = ?
    ]], {identifier, slot})

    if result then
        result.appearance = json.decode(result.appearance)
    end
    return result
end

-- Spawn handler
RegisterNetEvent('character:loaded', function(slot)
    local src = source
    local char = LoadCharacter(src, slot)
    if char then
        TriggerClientEvent('character:applyAppearance', src, char.appearance)
    end
end)

Интеграция одежды и вариации компонентов

Одежда в GTA V управляется через вариации компонентов и вариации пропов. Компоненты охватывают части тела, такие как торс, ноги, ноги, аксессуары и нижнее белье, в то время как пропы отвечают за прикрепляемые предметы, такие как шляпы, очки, серьги и часы. SetPedComponentVariation native принимает идентификатор компонента, drawable ID, texture ID и palette ID. Сложность в том, что доступные drawable различаются между мужскими и женскими моделями педов, а некоторые комбинации drawable и texture недопустимы. Ваш NUI должен запрашивать максимальное количество drawable для каждого компонента с помощью GetNumberOfPedDrawableVariations и максимальное количество текстур для каждого drawable с помощью GetNumberOfPedTextureVariations. Создайте селектор одежды, который динамически заполняет варианты в зависимости от выбранного пола, чтобы игроки видели только допустимые комбинации. Храните данные одежды вместе с данными внешности и применяйте их во время спавна, используя те же native-функции изменения компонентов.

Меры проверки и защиты от злоупотреблений

Никогда не доверяйте данным, поступающим от клиента без проверки. Игроки с модифицированными клиентами могут отправлять значения внешности вне нормальных диапазонов, что может привести к сбоям у других клиентов или эксплойтам визуальных багов. Валидируйте каждое поле на стороне сервера перед сохранением в базу данных. Индексы наследия должны быть от 0 до 45, значения смешивания от 0.0 до 1.0, значения черт лица от -1.0 до 1.0, а индексы наложений в пределах допустимого диапазона для каждого типа наложения. Отклоняйте или ограничивайте любые значения вне диапазона. Кроме того, реализуйте ограничение частоты обновлений внешности во время создания, чтобы предотвратить спам со стороны злонамеренных клиентов. Кулдаун в 100 миллисекунд между обновлениями незаметен для легитимных игроков, но останавливает автоматический спам. Наконец, заблокируйте процесс создания персонажа за счет правильного управления сессией, чтобы игроки не могли вызывать события создания вне предусмотренного потока.

Готовы начать?

Возьмите скрипты в нашем магазине или заходите в Discord за поддержкой, обновлениями и анонсами.