BG-BACKGROUND
# Desarrollo e Ingeniería

Lua desde cero para FiveM: guía práctica para empezar a programar

Descubre cómo aprender Lua para FiveM desde cero. Guía práctica con ejemplos listos, explicación cliente-servidor, buenas prácticas y apoyo de la comunidad Zeew Space.

Lua desde cero para FiveM: guía práctica para empezar a programar

Sí, puedes empezar hoy mismo aunque nunca hayas escrito código. Lua es sencillo, rápido de leer y perfecto para crear cosas reales en servidores de FiveM. En esta guía te explico lo esencial, te doy ejemplos listos y te muestro el camino para seguir creciendo sin perderte.

Resumen rápido (qué te llevas)

  • Qué es Lua y por qué encaja tan bien en FiveM
  • Cómo funciona cliente ↔ servidor y los eventos
  • Tu primer recurso (estructura + fxmanifest.lua)
  • Snippets útiles: comandos, mensajes, eventos cliente/servidor
  • Buenas prácticas y errores comunes a evitar
  • Siguientes pasos para avanzar sin atascarte

¿Qué es Lua y por qué se usa en FiveM?

Lua es un lenguaje de scripting ligero y muy fácil de aprender. Nació para “vivir dentro” de otros sistemas (como motores de juego), así que en FiveM encaja perfecto para:

  • Crear lógicas de gameplay (trabajos, misiones, tiendas, comandos).
  • Personalizar NPCs, vehículos y objetos.
  • Conectar con base de datos desde el servidor.
  • Controlar flujos entre cliente (jugador) y servidor.

Piensa en Lua como el pegamento que une tus ideas con lo que pasa en el juego—rápido de escribir, fácil de leer y con resultados inmediatos.

Por qué Lua es ideal si empiezas desde cero

  • Sintaxis simple: haces mucho con pocas líneas.
local nombre = "Zeew" print("Hola, " .. nombre)
  • Aprendes “lo de verdad”: variables, condiciones, funciones, eventos…
  • Feedback inmediato: ves cambios al instante dentro de FiveM.

Concepto clave en FiveM: cliente ↔ servidor

En FiveM trabajarás en dos lados:

  • Cliente: lo que corre en la PC del jugador (UI, efectos, notificaciones).
  • Servidor: lógica compartida (economía, permisos, validaciones, DB).

Se comunican con eventos:

  • Cliente → Servidor: TriggerServerEvent("evento", data)
  • Servidor → Cliente: TriggerClientEvent("evento", playerId, data)

Esta separación te obliga a pensar en seguridad: valida en el servidor, nunca confíes en lo que llega del cliente.

Tu primer recurso: estructura mínima

Crea una carpeta dentro de resources/[local]/lua_hello/ con estos archivos:

fxmanifest.lua

fx_version 'cerulean' game 'gta5' author 'Zeew Space' description 'Recurso de ejemplo: comandos y mensajes' version '1.0.0' client_scripts { 'client.lua' } server_scripts { 'server.lua' }

client.lua (cliente)

RegisterNetEvent('zeew:notify', function(msg) -- Muestra un mensaje en el chat del jugador TriggerEvent('chat:addMessage', { args = { '^2Servidor', msg } }) end)

server.lua (servidor)

-- Comando /saluda [nombre] RegisterCommand('saluda', function(source, args) local nombre = args[1] or 'jugador' local msg = ('¡Hola, %s! Bienvenido a ZeewRP.'):format(nombre) if source > 0 then -- Mensaje solo para quien ejecuta el comando TriggerClientEvent('zeew:notify', source, msg) else -- Ejecutado desde consola: envíalo a todos TriggerClientEvent('zeew:notify', -1, msg) end end, false)

Cómo probar

  1. Añade ensure lua_hello en tu server.cfg.
  2. Arranca el servidor y entra.
  3. En el chat, escribe: /saluda Zeew.

Snippets útiles para seguir creando

1) Temporizadores sin bloquear (cliente o servidor)

CreateThread(function() while true do -- Lógica repetitiva aquí Wait(1000) -- 1 segundo; evita 0ms para no saturar end end)

2) Evento cliente → servidor

-- CLIENTE RegisterCommand('pedir', function() TriggerServerEvent('zeew:pedido', { item = 'agua', cantidad = 1 }) end) -- SERVIDOR RegisterNetEvent('zeew:pedido', function(data) local src = source -- Valida datos local item = tostring(data.item or '') local cantidad = tonumber(data.cantidad or 0) if item ~= '' and cantidad > 0 then -- Aquí harías lógica de inventario/DB TriggerClientEvent('zeew:notify', src, ('Te dimos %dx %s.'):format(cantidad, item)) else TriggerClientEvent('zeew:notify', src, 'Pedido inválido.') end end)

3) Tabla (array/diccionario) básica

local precios = { agua = 5, pan = 7, cafe = 10 } local function precioDe(nombre) return precios[nombre] or 0 end

Buenas prácticas (te evitan dolores de cabeza)

  • Nunca hagas bucles while true do con Wait(0): usa 100–500ms si no es crítico.

  • Valida todo en servidor (rango de valores, permisos, nil).

  • Separa config de lógica (config.lua vs server.lua/client.lua).

  • Loguea con contexto:

    print(('[ZEEW] jugador %s hizo X'):format(source))
  • Nombra eventos con prefijo único (zeew:algo) para evitar colisiones.

  • Evita “copiar-pegar ciego”: entiende qué hace cada línea antes de publicarla.

Errores comunes (y cómo evitarlos)

  • Confiar en el cliente: cualquier dato que te mande un jugador es sospechoso; valida y limita en servidor.
  • No usar -1 cuando quieres “a todos”: si mandas a source y estás en consola, no llega a nadie.
  • Spamear prints: usa prints con prefijo y desactiva debug en producción.
  • Variables globales sin querer: declara siempre con local.

Ruta de aprendizaje sugerida

  1. Base de Lua: variables, tablas, funciones, condiciones, bucles.
  2. Cliente/Servidor en FiveM: eventos, comunicación y permisos.
  3. Pequeños recursos: un comando, un menú, una notificación personalizada.
  4. Persistencia: guarda datos (licencias, inventario) del lado servidor.
  5. Optimización: reduce bucles, mide tiempos, cuida el rendimiento.
  6. Escalar: estructura carpetas, módulos y separa responsabilidades.

Preguntas frecuentes (FAQ)

¿Necesito experiencia previa? No. Con los ejemplos de esta guía puedes publicar algo funcional el primer día.

¿Lua solo sirve para FiveM? No. También se usa en otros juegos y herramientas (por eso aprenderlo es una inversión que “abre puertas”).

¿Debo usar un framework (ESX/QBCore)? No para empezar. Comienza “vanilla” y súmate a un framework cuando entiendas bien eventos, permisos y servidor.

Siguientes pasos (para no quedarte en el “hola mundo”)