Le système d'inventaire est la pierre angulaire des jeux RPG et de survie sur Roblox. Une mauvaise conception entraîne duplication d'objets et mauvaise ergonomie mobile.
En adoptant une validation serveur stricte, des structures de données optimisées et le verrouillage de session DataStore, les créateurs garantissent une expérience fluide et sécurisée.
1. Modèles d'Inventaire: Emplacements Fixes vs. Grille vs. Poids
Choisir la structure adaptée à votre gameplay:
- Emplacements Fixes: Modèle barre d'action classique avec tableau indexé. Recherches en O(1) et sérialisation aisée.
- Grille Spatiale (Tetris): Objets occupant plusieurs cases façon Diablo. Nécessite une matrice de collision 2D.
- Budget d'Encombrement: Chaque objet a une masse; dépasser la limite réduit la vitesse de déplacement.
2. Autorité Serveur & Interface Utilisateur Optimiste
Une réactivité instantanée sans faille de sécurité:
- Prédiction Optimiste: L'icône se déplace immédiatement sur l'écran sans attendre l'aller-retour serveur.
- Validation Serveur: Contrôle de propriété, de limites et de poids avant validation.
- Rétablissement (Rollback): En cas de refus serveur, l'icône revient fluidement à son emplacement initial.
3. Structures de Données & Sérialisation des Piles
Organisation efficace des attributs en Luau:
- Modèle de Base vs. Instance: Propriétés statiques dans ReplicatedStorage, données dynamiques (UUID, durabilité) associées au joueur.
- Logique de Fusion de Piles: Calcul précis de l'espace libre et transfert atomique des quantités.
- Compression de Sauvegarde: Nettoyage des cases vides pour respecter le quota DataStore de 4 Mo.
-- Gestionnaire d'inventaire autoritaire côté serveur
local InventoryManager = {}
InventoryManager.__index = InventoryManager
local ItemDatabase = require(game.ReplicatedStorage.ItemDatabase)
function InventoryManager.new(player, maxSlots, maxWeight)
local self = setmetatable({}, InventoryManager)
self.Player = player
self.MaxSlots = maxSlots or 30
self.MaxWeight = maxWeight or 100
self.Slots = table.create(self.MaxSlots, false)
self.CurrentWeight = 0
self.IsLocked = false
return self
end
function InventoryManager:AddItem(itemId, amount)
if self.IsLocked then return false, "INVENTORY_LOCKED" end
local itemData = ItemDatabase[itemId]
if not itemData then return false, "INVALID_ITEM" end
local addedWeight = itemData.Weight * amount
if self.CurrentWeight + addedWeight > self.MaxWeight then
return false, "OVER_ENCUMBERED"
end
for slotIndex = 1, self.MaxSlots do
local slot = self.Slots[slotIndex]
if slot and slot.Id == itemId and slot.Count < itemData.MaxStack then
local space = itemData.MaxStack - slot.Count
local toAdd = math.min(space, amount)
slot.Count = slot.Count + toAdd
amount = amount - toAdd
self.CurrentWeight = self.CurrentWeight + (itemData.Weight * toAdd)
if amount <= 0 then return true end
end
end
for slotIndex = 1, self.MaxSlots do
if not self.Slots[slotIndex] then
self.Slots[slotIndex] = {
UUID = game:GetService("HttpService"):GenerateGUID(false),
Id = itemId,
Count = amount,
Durability = itemData.MaxDurability
}
self.CurrentWeight = self.CurrentWeight + (itemData.Weight * amount)
return true
end
end
return false, "INVENTORY_FULL"
end
return InventoryManager
4. Sécurité Anti-Duplication & Verrous de Session
Élimination des failles lors des échanges et déconnexions:
- Verrouillage MemoryStore: Clé distribuée temporaire lors des transferts d'objets pour éviter les doubles dépenses.
- Transactions d'Échange Atomiques: Validation simultanée sur une même frame serveur ou annulation intégrale.
- Régulation des Requêtes: Cooldown de 100 ms pour bloquer les attaques par saturation de paquets.
5. Ergonomie Mobile & Gestes Tactiles
Navigation fluide sur smartphones et tablettes:
- Cibles Tactiles de 44px Minimum: Ajustement dynamique de l'UIScale pour éviter les erreurs de manipulation.
- Menus Radiaux par Appui Long: Remplacement du clic droit pour utiliser, séparer ou jeter un objet.
- Retour Haptique: Micro-vibrations via HapticService lors de l'équipement pour un retour physique agréable.
Frequently Asked Questions
Pourquoi l'inventaire doit-il être géré côté serveur?
Gérer les calculs côté client permet l'injection d'objets illicites. Le serveur garantit l'intégrité de l'économie.
Comment l'interface optimiste supprime-t-elle la latence?
L'objet se déplace immédiatement à l'écran; il ne revient en arrière que si le serveur rejette l'action.
Qu'est-ce que le verrouillage de session DataStore?
Un mécanisme empêchant plusieurs serveurs de modifier simultanément les données d'un même joueur.
Comment fiabiliser le glisser-déposer sur mobile?
En déplaçant une icône légère sous le doigt et en n'évaluant la case cible qu'au relâchement du contact.