Animazioni e prop di FiveM: flag TaskPlayAnim, attacca all'osso, elimina

Riproduci animazioni e attacca prop in FiveM Lua: RequestAnimDict, flag TaskPlayAnim 1, 16, 32 e 49, ClearPedTasks, AttachEntityToEntity a un osso, scenari e pulizia.

Vuoi che un giocatore beva un caffè, tenga un telefono o usi uno strumento: un'animazione, spesso con un prop nella mano. Se fatto male, l'animazione non fa nulla, il prop galleggia ai piedi del giocatore o rimane nel mondo per sempre. Questa guida mostra la sequenza corretta e la pulizia.

Carica, riproduci, cancella

Un'animazione vive in un dizionario. Il dizionario deve essere caricato prima di riprodurre da esso:

lua
local function playAnim(ped, dict, anim, flag, duration)
    RequestAnimDict(dict)
    while not HasAnimDictLoaded(dict) do
        Wait(0)
    end
    TaskPlayAnim(ped, dict, anim, 8.0, -8.0, duration or -1, flag or 0, 0.0, false, false, false)
end

Se HasAnimDictLoaded non è mai true, il nome del dizionario è sbagliato e questo ciclo si blocca, quindi aggiungi un timeout quando il nome proviene dalla config. Con ox_lib, una riga sostituisce il ciclo:

lua
lib.requestAnimDict('mp_player_inteat@burger')

TaskPlayAnim accetta il ped, il dizionario, l'animazione, il blend in, il blend out, la durata in ms (-1 = fino a quando non fermato), il flag, e una velocità di riproduzione. Rilascia il dizionario quando hai finito con RemoveAnimDict(dict).

I flag di animazione

Il flag è una bitmask, quindi i valori si sommano. Quelli che utilizzerai:

Flag Effetto
0 Riproduci una volta, il giocatore non può muoversi
1 Loop
16 Solo corpo superiore, le gambe continuano a camminare
32 Il giocatore mantiene il controllo
49 1 + 16 + 32: loop, corpo superiore, controllabile

Per un'animazione da tenere in mano (telefono, drink, sigaretta), 49 è la scelta solita: fa il loop, solo il corpo superiore è animato, e il giocatore può ancora camminare. Per un'azione one-shot dove il giocatore dovrebbe stare fermo, usa 0, o 1 se dovrebbe fare il loop.

Interrompi l'animazione

lua
local ped = PlayerPedId()
ClearPedTasks(ped)                 -- stop and let the ped blend out
-- or, if it is stuck:
ClearPedTasksImmediately(ped)      -- cut instantly, can look abrupt
StopAnimTask(ped, dict, anim, 1.0) -- stop only that animation

Usa StopAnimTask quando diverse cose vengono eseguite sul ped, poiché ClearPedTasks annulla anche la camminata o lo scenario sottostante. ClearPedTasksImmediately corregge un ped bloccato ma lo fa anche uscire dai veicoli, quindi conservalo per il recupero.

Un prop nella mano

Un prop è un oggetto che crei e attacchi a un osso del ped. La sequenza: carica il modello, crea l'oggetto, attaccalo, riproduci l'animazione.

lua
local prop

local function attachProp(ped, model, bone, x, y, z, rx, ry, rz)
    local hash = joaat(model)
    RequestModel(hash)
    while not HasModelLoaded(hash) do Wait(0) end

    local coords = GetEntityCoords(ped)
    prop = CreateObject(hash, coords.x, coords.y, coords.z + 0.2, true, true, false)

    AttachEntityToEntity(
        prop, ped, GetPedBoneIndex(ped, bone),
        x, y, z, rx, ry, rz,
        true, true, false, true, 1, true
    )
    SetModelAsNoLongerNeeded(hash)
    return prop
end

I pezzi:

  • CreateObject(model, x, y, z, isNetwork, netMissionEntity, doorFlag): passa isNetwork = true se altri giocatori dovrebbero vedere il prop, che è normalmente quello che vuoi per qualcosa in una mano.
  • GetPedBoneIndex(ped, boneId) converte un id osso come 28422 (posizionamento mano destra) o 18905 (mano sinistra) in un indice. Cerca l'elenco degli id osso per altri.
  • x, y, z e rx, ry, rz sono gli offset e la rotazione relativi all'osso. Questi hanno bisogno di messa a punto per prop; non c'è scorciatoia, quindi cambia un valore e prova.
  • I booleani dopo la rotazione sono soft pinning, collisione e flag simili. Collisione false impedisce al prop di spingere il ped in giro.

Mettilo insieme

lua
local function eatBurger()
    local ped = PlayerPedId()
    attachProp(ped, 'prop_cs_burger_01', 28422, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0)
    lib.requestAnimDict('mp_player_inteat@burger')
    TaskPlayAnim(ped, 'mp_player_inteat@burger', 'mp_player_int_eat_burger', 8.0, -8.0, 3000, 49, 0.0, false, false, false)
    Wait(3000)
    ClearPedTasks(ped)
    deleteProp()
end

Se il prop non sembra giusto nella mano, correggi prima gli offset, poi l'osso. Se il nome di un'altra animazione non esiste in un dizionario, TaskPlayAnim non fa silenziosamente nulla, quindi controlla doppiamente la coppia (i nomi esatti del dizionario e dell'animazione, in minuscolo come scritto).

Elimina il prop

Pulisci sempre. Un prop che non viene eliminato rimane nel mondo, ancora attaccato a un ped che non lo tiene più:

lua
function deleteProp()
    if prop and DoesEntityExist(prop) then
        DetachEntity(prop, true, true)
        DeleteEntity(prop)
    end
    prop = nil
end

AddEventHandler('onResourceStop', function(resource)
    if resource ~= GetCurrentResourceName() then return end
    deleteProp()
    ClearPedTasks(PlayerPedId())
end)

Elimina anche il prop alla morte e quando il giocatore esce dall'animazione, non solo sul percorso felice. I prop persi sono una fonte classica di "oggetti ovunque" e un server lento; vedi resmon high ms.

Scenari

Per le animazioni in piedi che includono i loro prop, come appoggiarsi, fumare o scrivere su una lavagna, usa un scenario invece:

lua
local ped = PlayerPedId()
TaskStartScenarioInPlace(ped, 'WORLD_HUMAN_CLIPBOARD', 0, true)

-- later
ClearPedTasks(ped)

Gli argomenti sono il ped, il nome dello scenario, un ritardo in ms (0 per nessuno) e se riprodurre l'animazione di entrata. Gli scenari attaccano e puliscono il loro prop per te, e sono l'opzione più facile quando l'animazione non ha bisogno di essere tenuta mentre cammini.

Per una versione pronta di animazione più prop più barra di progresso, lib.progressBar di ox_lib accetta le opzioni anim e prop; vedi notifiche e barre di progresso e Aspetta e thread per le abitudini di attesa dietro i cicli sopra.

Checklist

Sintomo Soluzione
L'animazione non fa nulla Richiedi il dizionario e aspetta che HasAnimDictLoaded sia true prima
Il ciclo si blocca al caricamento Il nome del dizionario è sbagliato; aggiungi un timeout
Giocatore congelato sul posto Flag 0 o 1 blocca il movimento; usa 49 per mantenere il controllo
Prop ai piedi, non alla mano Osso sbagliato o nessun AttachEntityToEntity; controlla GetPedBoneIndex
Prop storto nella mano Messa a punto x, y, z e offset di rotazione
Prop rimasti nel mondo DeleteEntity(prop) alla fine, morte e arresto della risorsa
Ped bloccato in una posa ClearPedTasks o, come ultimo ricorso, ClearPedTasksImmediately

Risposte rapide

Perché la mia animazione non viene riprodotta?

Il dizionario di animazioni non era ancora caricato. Chiama RequestAnimDict, aspetta fino a quando HasAnimDictLoaded è true, e solo allora chiama TaskPlayAnim. Con ox_lib, lib.requestAnimDict(dict) lo fa per te.

Quale flag TaskPlayAnim dovrei usare?

Usa 1 per il loop, 16 per riprodurre solo il corpo superiore, 32 per lasciare il giocatore in controllo, e 49 per loop più corpo superiore più controllabile. Queste sono le combinazioni comuni per le animazioni che tieni mentre cammini.

Come rimuovo un prop dopo l'animazione?

Chiama DeleteEntity(prop) quando l'animazione termina o lo script si ferma, e rilascia il modello con SetModelAsNoLongerNeeded. I prop rimasti accumulano nel mondo.

Script senza questo problema

Hookah SystemNarghilè e arredi lounge posizionabili, con oltre 50 gusti ed effetti.Vedi script →Vape SystemOltre 50 svapo con gusti, fumo ed effetti — dal mango alla super velocità.Vedi script →Super Leaf BlowerUn soffiatore che spinge giocatori, auto, NPC e props. Funziona con qualsiasi framework.Vedi script →

Continua a leggere