>
Tutorial 2026-05-14

Desenvolvimento do Ecrã de Criação de Personagem em FiveM

TDYSKY

TDYSKY

Fundador & Lead Developer na Agency Scripts

Por que a criação de personagens é importante no RPG

A criação de personagem é o primeiro momento interativo que um jogador experimenta em seu servidor de RPG FiveM. Ele dá o tom para tudo o que se segue. Um criador de personagem sofisticado e envolvente diz aos novos jogadores que seu servidor foi construído profissionalmente e vale a pena investir seu tempo. Um servidor básico ou cheio de bugs os envia diretamente para o navegador do servidor em busca de alternativas. Além das primeiras impressões, o criador do personagem define a identidade visual que cada jogador carrega ao longo de toda a sua experiência de RPG. Ele determina combinações de heranças, características faciais, estilos de cabelo, roupas e detalhes biográficos como nome e data de nascimento. Fazer isso direito significa construir um sistema que se comunique com o sistema de aparência nativo do GTA V, apresente as opções por meio de uma interface NUI intuitiva, persista as seleções em um banco de dados e as carregue de volta de forma confiável sempre que o jogador aparecer.

Compreendendo o sistema de aparência Ped do GTA V

GTA V usa um sistema de aparência baseado em herança, onde o rosto de um personagem é mesclado a partir de dois modelos parentais. Existem 46 possíveis mães e pais, cada um com estruturas faciais distintas. O nativo SetPedHeadBlendData controla essa mistura, aceitando valores de mistura de forma e pele entre 0,0 e 1,0 que determinam o quanto o personagem se parece com cada pai. Além da herança, o jogo oferece 20 categorias de sobreposição por meio de SetPedHeadOverlay cobrindo recursos como manchas, pelos faciais, sobrancelhas, envelhecimento, maquiagem e danos à pele. Cada sobreposição tem seu próprio valor de opacidade e pode ser colorida de forma independente usando SetPedHeadOverlayColor. O cabelo é tratado separadamente através de SetPedComponentVariation para a modelo e SetPedHairColor para cores e mechas. A cor dos olhos usa SetPedEyeColor com valores que variam de 0 a 31. Compreender esses nativos é essencial porque sua interface NUI precisa mapear controles deslizantes e seletores fáceis de usar para essas chamadas de função específicas.

-- 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

Construindo a Interface NUI

A NUI (Natural User Interface) é a sobreposição de HTML, CSS e JavaScript com a qual os jogadores interagem enquanto criam seu personagem. Um criador de personagem bem projetado divide o processo em etapas lógicas: primeiro informações biográficas, depois seleção de herança, características faciais, sobreposições como pelos faciais e maquiagem, estilo de cabelo e, finalmente, roupas. Cada etapa deve mostrar atualizações de visualização em tempo real no modelo do personagem para que os jogadores possam ver exatamente como são suas escolhas. Use um layout com guias ou estilo assistente para que os jogadores não fiquem sobrecarregados com dezenas de opções ao mesmo tempo. Os controles deslizantes de intervalo funcionam bem para valores contínuos, como mistura de formas e características faciais, enquanto os seletores de grade com visualizações em miniatura funcionam melhor para opções discretas, como penteados e itens de roupas. Envie cada alteração para o script do cliente via fetch ou o sistema de mensagens NUI para que o ped seja atualizado instantaneamente.

<!-- 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>

Sistema de câmera para visualização de personagens

Um sistema de câmera dedicado é crucial para uma experiência refinada de criação de personagens. Os jogadores precisam ver close-ups das características faciais ao ajustar misturas e sobreposições de herança, fotos médias para cabelos e roupas da parte superior do corpo e vistas de corpo inteiro para calças e sapatos. Implemente um controlador de câmera que interpole suavemente entre posições predefinidas com base em qual etapa de criação está ativa. Use CreateCam com o tipo DEFAULT_SCRIPTED_CAMERA e RenderScriptCams para assumir o controle da câmera do jogo. Para rotação, permita que os jogadores arrastem o mouse para orbitar em torno de seu personagem, ajustando a direção da câmera enquanto a mantêm apontada para o pedestre. Uma animação ociosa sutil no ped, como o cenário WORLD_HUMAN_STAND_IMPATIENT, mantém o personagem com aparência natural durante o processo de criação, em vez de ficar em uma pose rígida em T.

-- 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

Salvando e carregando dados de personagens

Todos os dados de aparência do personagem precisam persistir em um banco de dados para que sobrevivam às reinicializações do servidor e possam ser carregados sempre que o jogador aparecer. Estruture sua tabela de banco de dados para armazenar a aparência completa como um blob JSON junto com campos biográficos como nome, sobrenome, data de nascimento, sexo e nacionalidade. Quando o jogador termina a criação e confirma seu personagem, o cliente envia o objeto de dados completo para o servidor, que valida os intervalos de entrada e o insere no banco de dados. Nos logins subsequentes, o servidor busca os dados do personagem durante o fluxo de spawn e os envia de volta ao cliente, que chama a mesma função ApplyAppearance usada durante a criação. Para servidores com vários personagens, armazene um identificador de slot de personagem para que cada jogador possa ter vários personagens com aparências independentes.

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

Integração de roupas e variações de componentes

As roupas no GTA V são gerenciadas por meio de variações de componentes e variações de acessórios. Os componentes cobrem partes do corpo como tronco, pernas, pés, acessórios e camisetas, enquanto os adereços lidam com itens anexáveis ​​como chapéus, óculos, brincos e relógios. O nativo SetPedComponentVariation recebe um ID de componente, ID de drawable, ID de textura e ID de paleta. O desafio é que os drawables disponíveis diferem entre os modelos ped masculinos e femininos, e algumas combinações de drawables e texturas são inválidas. Sua NUI precisa consultar o número máximo de drawables para cada componente usando GetNumberOfPedDrawableVariations e as texturas máximas para cada drawable usando GetNumberOfPedTextureVariations. Construa seu seletor de roupas para preencher dinamicamente as opções com base no gênero selecionado para que os jogadores vejam apenas combinações válidas. Armazene dados de roupas junto com dados de aparência e aplique-os durante o fluxo de spawn usando a mesma variação de componentes nativos.

Medidas de validação e antiabuso

Nunca confie em dados provenientes do cliente sem validação. Jogadores com clientes modificados podem enviar valores de aparência fora dos limites normais, potencialmente travando outros clientes ou explorando falhas visuais. Valide todos os campos do lado do servidor antes de salvar no banco de dados. Os índices de herança devem estar entre 0 e 45, misturar valores entre 0,0 e 1,0, valores de recursos faciais entre -1,0 e 1,0 e índices de sobreposição dentro do intervalo válido para cada tipo de sobreposição. Rejeite ou limite quaisquer valores fora da faixa. Além disso, implemente a limitação de taxa em eventos de atualização de aparência durante a criação para evitar que clientes mal-intencionados inundem o servidor com alterações rápidas de aparência. Um tempo de espera de 100 milissegundos entre atualizações é imperceptível para jogadores legítimos, mas impede o spam automatizado. Por fim, bloqueie o fluxo de criação de personagem por meio do gerenciamento de sessão adequado para que os jogadores não possam acionar eventos de criação fora do fluxo pretendido.

Partilhar este artigo

Pronto para melhorar o teu servidor?

Explora os nossos scripts FiveM premium na loja Agency Scripts ou junta-te à nossa comunidade no Discord para suporte e atualizações.