games / lua
Bases : variables, types et opérateurs
Explication
Un peu d'histoire
Lua est créé en 1993 au Brésil, par Roberto Ierusalimschy, Luiz Henrique de Figueiredo et Waldemar Celes, à l'université PUC-Rio de Rio de Janeiro. "Lua" signifie tout simplement "lune" en portugais. Dès sa conception, le langage est pensé pour être léger, rapide et surtout facile à intégrer ("embarquer") dans une application déjà écrite en C — plutôt qu'un langage autonome destiné à tourner seul.
Pourquoi apprendre Lua aujourd'hui
Lua est extrêmement présent dans le monde du jeu vidéo comme langage de script : World of Warcraft, Roblox, ou encore les serveurs de jeu FiveM l'utilisent pour permettre aux joueurs et créateurs de personnaliser le comportement du jeu sans toucher au moteur écrit en C/C++. On le retrouve aussi dans des outils bien connus comme l'éditeur Neovim ou la base de données Redis. Sa légèreté et sa facilité d'intégration en font le langage de choix chaque fois qu'une application doit devenir "scriptable" par ses utilisateurs.
Ce que vous allez apprendre
- Déclarer une variable locale et comprendre pourquoi c'est presque toujours le bon choix
- Distinguer les types fondamentaux de Lua (
nil,boolean,number,string,table,function) - Reconnaître la distinction
integer/floatà l'intérieur du typenumber(Lua 5.3+) - Appliquer la règle du "truthy/falsy" propre à Lua, différente de la plupart des autres langages
- Utiliser les bons opérateurs Lua (
..pour concaténer,~=pour "différent de") sans les confondre avec d'autres langages
Dans quel contexte ?
Imagine un créateur de contenu qui script sa toute première interaction sur un serveur FiveM : afficher le nom du joueur, son niveau et un statut "en ligne/hors ligne" dans la console. Rien de complexe en apparence, mais chaque variable posée ici pose déjà une question de portée (doit-elle être visible d'un autre script ?) et de type (un niveau est-il vraiment un texte ou un nombre ?). Ces choix, pris dès les toutes premières lignes de code, déterminent si le script restera lisible et sans bug une fois qu'il grossira.
Variables et portée : la première décision qui compte
Une variable Lua est globale par défaut si l'on oublie le mot-clé local — c'est un choix de conception historique qui surprend souvent les débutants venant d'autres langages. Une variable globale est visible partout dans le programme, ce qui semble pratique au début mais devient vite une source de bugs difficiles à tracer : deux parties du code peuvent se marcher dessus sans le savoir. Prendre l'habitude d'écrire local systématiquement, dès cette première leçon, évite ce piège pour tout le reste du cours.
Prérequis
Aucune connaissance préalable n'est nécessaire : cette leçon suppose seulement que tu sais ouvrir un fichier .lua et l'exécuter (par exemple avec lua monscript.lua en ligne de commande, ou via un serveur FiveM en développement).
Un système de types minimaliste mais avec des subtilités
Lua n'a que quelques types de base (nil, boolean, number, string, table, function...), ce qui le rend simple à apprendre. Mais deux subtilités méritent une attention particulière : la distinction interne integer/float dans le type number, et la règle du "truthy/falsy" — contrairement à beaucoup de langages où 0 ou une chaîne vide sont considérés comme faux, en Lua SEULS nil et false sont faux. Tout le reste, y compris 0, est vrai dans un test conditionnel.
| Type Lua | Exemple de valeur | Falsy ? |
|---|---|---|
nil | nil | Oui |
boolean | true / false | false seulement |
number | 42, 3.14 | Non, même 0 |
string | "texte" | Non, même "" |
table | {1, 2, 3} | Non |
function | print | Non |
Piège fréquent
Venant de JavaScript ou Python, on s'attend souvent à ce que 0 ou "" soient "faux" dans un if. En Lua, ce n'est jamais le cas : seuls nil et false déclenchent la branche else. Un test comme if userInput then sur une chaîne vide "" s'exécutera donc toujours comme si une vraie valeur était présente.
Le point de départ de tout le cours
Cette leçon pose le vocabulaire de base (variables, types, opérateurs) sur lequel s'appuient toutes les suivantes — en particulier la notion de portée locale, qui redeviendra centrale dès la leçon sur les fonctions et les closures.
Commandes & code
Bases : variables, types et opérateurs
-- Déclaration de variable : locale (recommandée) ou globale (à éviter, pollue l'espace global)
local playerName = "Alice" -- string
local playerLevel = 12 -- number (Lua ne distingue pas int/float par défaut avant 5.3)
local isOnline = true -- boolean
local inventory = nil -- nil = absence de valeur
globalScore = 100 -- variable globale : visible partout, source classique de bugs, à éviter-- Lua 5.3+ distingue les entiers (integer) et les flottants (float) sous le type "number"
print(math.type(10)) -- "integer"
print(math.type(10.0)) -- "float"
print(math.type(10 / 2)) -- "float" : la division "/" retourne TOUJOURS un float
print(math.type(10 // 3))-- "integer" : "//" est la division entière (floor division)-- Les 8 types fondamentaux de Lua
print(type("texte")) -- "string"
print(type(42)) -- "number"
print(type(true)) -- "boolean"
print(type(nil)) -- "nil"
print(type({})) -- "table"
print(type(print)) -- "function"
print(type(coroutine.create(function() end))) -- "thread"
-- "userdata" : type représentant des données C opaques (utilisé côté moteur hôte, voir dernière leçon)-- Opérateurs arithmétiques
print(7 + 3, 7 - 3, 7 * 3, 7 / 3, 7 // 3, 7 % 3, 7 ^ 2)
-- 10 4 21 2.3333333333333 2 1 49.0 ("^" = puissance, retourne toujours un float)
-- Opérateurs relationnels et logiques
print(5 == 5, 5 ~= 3, 5 < 10) -- "~=" est l'opérateur "différent de" en Lua (pas "!=")
print(true and false, true or false, not true)-- Falsy / truthy en Lua : SEULS nil et false sont "falsy", tout le reste est "truthy"
-- Piège classique venant d'autres langages : 0 et "" sont TRUTHY en Lua (contrairement à JS/Python)
if 0 then print("0 est truthy en Lua") end -- s'affiche
if "" then print("chaîne vide est truthy") end -- s'affiche
local x = nil
local y = x or "valeur par défaut" -- pattern idiomatique Lua pour une valeur par défaut
print(y) -- "valeur par défaut"-- Concaténation de chaînes avec ".." (deux points), pas "+"
local first = "Techno"
local second = "logik"
print(first .. second) -- "Technologik"
print("Score: " .. 42) -- concaténation implicite number -> string : "Score: 42"
-- Conversion explicite entre types
print(tostring(42)) -- "42"
print(tonumber("42") + 1) -- 43
print(tonumber("abc")) -- nil (échec de conversion, à toujours vérifier)-- Portée des variables locales : bloc-scopées (do...end crée un nouveau bloc)
local level = 1
do
local level = 2 -- masque (shadow) la variable externe DANS ce bloc uniquement
print(level) -- 2
end
print(level) -- 1, la variable externe n'est pas modifiéeRésumé
localest le mot-clé par défaut à utiliser ; les globales sont une source classique de bugs.- Lua distingue
integer/floatsous le typenumberdepuis la version 5.3. - Seuls
niletfalsesont falsy ;0et""sont truthy, contrairement à beaucoup d'autres langages. - La concaténation se fait avec
.., la comparaison de différence avec~=.
Exercices pratiques
Mission : traquer un bug de statut sur un serveur FiveM
Objectif : Analyser un script de statut joueur pour trouver pourquoi un statut vide s'affiche comme actif, puis corriger le code.
Contexte
Un créateur de contenu FiveM te transmet ce script qui affiche le statut d'un joueur :
local playerTag = ""
local playerLevel = 10 / 2
if playerTag then
print("Tag défini : " .. playerTag)
else
print("Aucun tag")
end
print(math.type(playerLevel))Il ne comprend pas pourquoi la console affiche Tag défini : (vide) alors qu'il pensait que playerTag étant une chaîne vide, la condition else s'exécuterait. Il se demande aussi pourquoi math.type(playerLevel) renvoie "float" alors qu'il a divisé deux entiers "ronds".