Saltar al contenido
Roblox Lab
Consejos para creadores

Seguridad en tus juegos de Roblox: por qué nunca debes confiar en el cliente

Publicado el 1 min de lectura

Cualquier cosa que se ejecuta en el dispositivo del jugador puede ser manipulada. Por eso, en un juego de Roblox las decisiones importantes (dar monedas, guardar progreso, aplicar daño) deben tomarse siempre en el servidor.

Leyenda:Información confirmadaConsejo generalPendiente de verificar

Cliente y servidor

Información confirmada

En Roblox, los Scripts se ejecutan en el servidor y los LocalScripts en el dispositivo de cada jugador. Para comunicarse usan RemoteEvents y RemoteFunctions. Un jugador malintencionado puede enviar al servidor cualquier dato a través de esos remotos, no solo lo que tu interfaz permite.

Valida todo en el servidor

Consejo general

Nunca envíes desde el cliente «dame 100 monedas». Envía la intención («quiero comprar el objeto X») y deja que el servidor compruebe si es posible:

-- Script en ServerScriptService
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local buyItem = ReplicatedStorage:WaitForChild("BuyItem") -- RemoteEvent

local PRICES = { Sword = 50, Shield = 30 }

buyItem.OnServerEvent:Connect(function(player, itemName)
	if typeof(itemName) ~= "string" then return end
	local price = PRICES[itemName]
	if not price then return end

	local coins = player:FindFirstChild("leaderstats")
		and player.leaderstats:FindFirstChild("Coins")
	if not coins or coins.Value < price then return end

	coins.Value -= price
	-- Entregar el objeto aquí, también desde el servidor
end)
  • Comprueba el tipo de cada argumento recibido.
  • Usa precios y reglas guardados en el servidor, nunca los que envía el cliente.
  • Comprueba distancias y tiempos de espera para acciones físicas o habilidades.

Guarda datos con cuidado

Información confirmada

Las llamadas a DataStoreService pueden fallar (por ejemplo, por límites de peticiones), así que envuélvelas en pcall y gestiona el error sin borrar el progreso del jugador:

local ok, result = pcall(function()
	return store:GetAsync("player_" .. player.UserId)
end)
if not ok then
	warn("No se pudieron cargar los datos:", result)
	-- No sobrescribas los datos guardados con valores vacíos
end

Guías relacionadas