Spawnar um veículo no FiveM: CreateVehicle vs CreateVehicleServerSetter

Spawne veículos da forma certa no FiveM: CreateVehicle de cliente com RequestModel, CreateVehicleServerSetter de servidor no OneSync, net ids, placas, chaves e carros desaparecendo.

Você spawna um veículo e ele aparece invisível, spawna sob o mapa, desaparece após um minuto, ou apenas o jogador que o spawnou consegue vê-lo. Há duas formas corretas de spawnar um carro, e cada uma tem um conjunto diferente de armadilhas. Este artigo mostra ambas, como definir a placa e entregar as chaves, e por que os carros spawnados desaparecem.

Spawne no cliente com CreateVehicle

A versão de cliente é a que a maioria dos scripts usa. O modelo deve estar carregado antes de você criar o veículo, ou CreateVehicle retorna 0:

lua
local function spawnVehicle(modelName, coords, heading)
    local model = joaat(modelName)

    if not IsModelInCdimage(model) or not IsModelAVehicle(model) then
        print('invalid vehicle model:', modelName)
        return nil
    end

    RequestModel(model)
    local timeout = GetGameTimer() + 5000
    while not HasModelLoaded(model) do
        if GetGameTimer() > timeout then
            print('model did not load:', modelName)
            return nil
        end
        Wait(0)
    end

    local vehicle = CreateVehicle(model, coords.x, coords.y, coords.z, heading, true, false)
    SetModelAsNoLongerNeeded(model)

    return vehicle
end

Os passos:

  1. IsModelInCdimage verifica que o modelo existe. Um erro de digitação ou um carro addon faltando para aqui em vez de congelar.
  2. RequestModel depois um loop em HasModelLoaded espera por ele, com um timeout.
  3. CreateVehicle toma o modelo, posição, heading, depois isNetwork (true para que outros jogadores vejam) e netMissionEntity.
  4. SetModelAsNoLongerNeeded libera a memória do modelo quando termina.

Se o veículo é um addon, veja como adicionar carros addon primeiro. Um modelo que não é streamed nunca carrega.

Dica: com ox_lib, lib.requestModel(model) faz o pedido e a espera para você, e gera erro em um timeout.

Coloque o jogador no banco do motorista e defina a placa:

lua
local vehicle = spawnVehicle('sultan', GetEntityCoords(PlayerPedId()), GetEntityHeading(PlayerPedId()))

if vehicle then
    SetVehicleNumberPlateText(vehicle, 'MIC 001')
    SetPedIntoVehicle(PlayerPedId(), vehicle, -1)
end

A placa tem no máximo 8 caracteres.

Spawne no servidor com CreateVehicleServerSetter

No OneSync, o servidor pode criar o veículo em si. Isso é mais confiável para scripts onde o servidor decide o spawn, como uma garagem ou um veículo de job, e nenhum cliente precisa ficar perto:

lua
RegisterNetEvent('my_script:spawnCar', function()
    local src = source
    local ped = GetPlayerPed(src)
    local coords = GetEntityCoords(ped)
    local heading = GetEntityHeading(ped)

    local vehicle = CreateVehicleServerSetter(joaat('sultan'), 'automobile', coords.x, coords.y, coords.z, heading)

    while not DoesEntityExist(vehicle) do
        Wait(0)
    end

    SetVehicleNumberPlateText(vehicle, 'MIC 001')
    TaskWarpPedIntoVehicle(ped, vehicle, -1)

    local netId = NetworkGetNetworkIdFromEntity(vehicle)
    TriggerClientEvent('my_script:vehicleSpawned', src, netId)
end)

O segundo argumento é o tipo de veículo como uma string: 'automobile', 'bike', 'boat', 'heli', 'plane', 'submarine', 'trailer' ou 'train'. Escolha o que corresponde ao modelo. Uma bicicleta criada como um automóvel se comportará de forma errada.

Ao contrário do cliente, você não requisita o modelo no servidor. A chamada também é assíncrona: a entidade pode não existir no momento em que retorna, então aguarde DoesEntityExist, com um timeout no código real.

Ative o OneSync no server.cfg, ou a chamada não funciona. Veja como ativar o OneSync.

Net ids: entregando o carro para um cliente

Um veículo criado no servidor tem um identificador de entidade que só existe no servidor. Um cliente não pode usá-lo. Para referenciar o carro entre máquinas, use seu network id, que é o mesmo em todos os lugares:

lua
-- server
local netId = NetworkGetNetworkIdFromEntity(vehicle)

No cliente, aguarde a entidade existir naquela máquina, depois converta:

lua
RegisterNetEvent('my_script:vehicleSpawned', function(netId)
    local timeout = GetGameTimer() + 5000
    while not NetworkDoesEntityExistWithNetworkId(netId) do
        if GetGameTimer() > timeout then return end
        Wait(0)
    end

    local vehicle = NetToVeh(netId)
    print('my vehicle is', vehicle)
end)

Nunca envie o identificador de entidade bruto sobre um evento: não significa nada em outra máquina.

Placas e chaves

Defina a placa logo após o veículo existir, como nos exemplos acima, e antes de entregar as chaves. As chaves dependem do script de chaves de veículo que seu servidor usa, já que cada script tem sua própria função. A maioria funciona com a placa, então a ordem usual é:

  1. Crie o veículo.
  2. Defina a placa com SetVehicleNumberPlateText.
  3. Chame a exportação ou evento do seu script de chaves com aquela placa.

Armazene a mesma placa em seu banco de dados, se o veículo for proprietário, para que a garagem possa encontrá-lo novamente. Verifique a documentação do script de chaves que você usa para a chamada exata. Não copie uma chamada de outro servidor.

Por que os carros spawnados desaparecem

Não relevante para ninguém. O jogo remove uma entidade em rede quando ninguém está perto dela. Um carro spawnado no servidor para um jogador que se afasta pode ser deletado.

O proprietário saiu. Uma entidade pertence a um jogador que a possui. Quando o proprietário de um veículo spawnado no cliente desconecta ou se afasta, pode ser removido. No servidor você pode definir o que acontece:

lua
SetEntityOrphanMode(vehicle, 2)

O modo órfão 2 é "manter a entidade", 0 é o padrão (deletar quando não relevante), e 1 a deleta quando o proprietário desconecta. Verifique a documentação nativa para sua compilação de servidor.

Não marcada como uma entidade de missão. No cliente, a limpeza ambiente pode deletar um carro que você criou. Marque-o para que o jogo a trate como sua:

lua
SetEntityAsMissionEntity(vehicle, true, true)

Um script de limpeza. Muitos servidores executam um script que remove veículos desocupados. Se seus carros desaparecem em um horário fixo, essa é a causa, não seu código de spawn.

Nunca spawnou. Um carro invisível ou ausente geralmente significa que o modelo não foi carregado, CreateVehicle retornou 0 e o script continuou. Sempre verifique o identificador retornado.

Delete carros você mesmo quando terminar, com DeleteEntity(vehicle), para que não se acumulem.

Lista de verificação

Sintoma Solução
CreateVehicle retorna 0 RequestModel e aguarde HasModelLoaded primeiro
Congelar em um nome de modelo ruim Verifique IsModelInCdimage antes de requisitar
Apenas o spawner vê o carro Passe isNetwork = true para CreateVehicle
CreateVehicleServerSetter não faz nada Ative o OneSync e aguarde DoesEntityExist
Cliente recebe um id de entidade inútil Envie o net id, depois use NetToVeh no cliente
Carro desaparece depois Marque como entidade de missão, defina o modo órfão, verifique scripts de limpeza
Jogador não consegue dirigir seu carro Dê as chaves com seu script de chaves, usando a placa

Respostas rápidas

Preciso de OneSync para usar CreateVehicleServerSetter?

Sim. A criação de entidades do lado do servidor precisa de OneSync ativado. Em um servidor sem ele, spawne o veículo no cliente com CreateVehicle.

Por que meu carro spawnado desaparece?

Um veículo em rede é deletado quando não é mais relevante para ninguém, ou quando seu proprietário sai, a menos que você diga ao jogo para mantê-lo. Marque-o como uma entidade de missão no cliente, ou defina seu modo órfão no servidor.

Como dou as chaves para o jogador?

Depende do script de chaves de veículo que seu servidor usa. A maioria tem uma exportação ou evento de cliente que toma a placa, então chame-o após definir a placa.

Scripts sem esse problema

Advanced BoostingBoosting de veículos pelo tablet: contratos da classe D à S+, crews e fila ao vivo.Ver script →Chameleon Paints82 pinturas camaleão que mudam de cor, num menu de um clique.Ver script →

Continue lendo