Roblox uses the Luau programming language. The following code samples and tables indicate some of the differences between syntaxes for C# and Luau.
Line Endings
You don't need semicolons in Luau, but they don't break the syntax.
Reserved Keywords
The following table has Luau's reserved keywords mapped to their C# equivalent. Note it doesn't show all C# keywords.
Lua | C# |
---|---|
and | |
break | break |
do | do |
if | if |
else | else |
elseif | else if |
then | |
end | |
true | true |
false | false |
for | for or foreach |
function | |
in | in |
local | |
nil | null |
not | |
or | |
repeat | |
return | return |
until | |
while | while |
Comments
Comments in Luau
-- Single line comment--[[ Resulting output:Block comment--]]
Comments in C#
// Single line comment/*Block comment*/
Strings
Strings in Luau
-- Multi-line stringlocal multiLineString = [[This is a string that,when printed, appearson multiple lines]]-- Concatenationlocal s1 = "This is a string "local s2 = "made with two parts."local endString = s1 .. s2
Strings in C#
// Multi-line stringstring multiLineString1 = "This is a string that,\nwhen printed, appears\n on multiple lines.";string multiLineString2 = @"This is a string that,when printed, appearson multiple lines";// Concatenationstring s1 = "This is a string ";string s2 = "made with two parts.";string endString = s1 + s2;
Tables
To learn more about tables in Luau, see Tables.
Dictionary Tables
You can use tables in Luau as dictionaries just like in C#.
Dictionary Tables in Luau
local dictionary = {val1 = "this",val2 = "is"}print(dictionary.val1) -- Outputs 'this'print(dictionary["val1"]) -- Outputs 'this'dictionary.val1 = nil -- Removes 'val1' from tabledictionary["val3"] = "a dictionary" -- Overwrites 'val3' or sets new key-value pair
Dictionary Tables in C#
Dictionary dictionary = new Dictionary(){{ "val1", "this" },{ "val2", "is" }};Console.WriteLine(dictionary["val1"]); // Outputs 'this'dictionary.Remove("val1"); // Removes 'val1' from dictionarydictionary["val3"] = "a dictionary"; // Overwrites 'val3' or sets new key-value pairdictionary.Add("val3", "a dictionary"); // Creates a new key-value pair
Numerically-Indexed Tables
You can use tables in Luau as arrays just like in C#. Indices start at 1 in Luau and 0 in C#.
Numerically-Indexed Tables in Luau
local npcAttributes = {"strong", "intelligent"}print(npcAttributes[1]) -- Outputs 'strong'print(#npcAttributes) -- Outputs the size of the list-- Append to the listtable.insert(npcAttributes, "humble")-- Another way...npcAttributes[#npcAttributes+1] = "humble"-- Insert at the beginning of the listtable.insert(npcAttributes, 1, "brave")-- Remove item at a given indextable.remove(npcAttributes, 3)
Numerically-Indexed Tables in C#
List npcAttributes = new List{"strong", "intelligent"};Console.WriteLine(npcAttributes[0]); // Outputs 'strong'Console.WriteLine(npcAttributes.Count); // Outputs the size of the list// Append to the listnpcAttributes.Add("humble");// Another way...npcAttributes.Insert(npcAttributes.Count, "humble");// Insert at the beginning of the listnpcAttributes.Insert(0, "brave");// Remove item at a given indexnpcAttributes.Remove(2);
Operators
Conditional Operators
Operator | Lua | C# |
---|---|---|
Equal To | == | == |
Greater Than | > | > |
Less Than | < | < |
Greater Than or Equal To | >= | >= |
Less Than or Equal To | <= | <= |
Not Equal To | ~= | != |
And | and | && |
Or | or | || |
Arithmetic Operators
Lua | C# | |
---|---|---|
Addition | + | + |
Subtraction | - | - |
Multiplication | * | * |
Division | / | / |
Modulus | % | % |
Exponentiation | ^ | ** |
Variables
In Luau, variables don't specify their type when you declare them. Luau variables don't have access modifiers, although you may prefix "private" variables with an underscore for readability.
Variables in Luau
local stringVariable = "value"-- "Public" declarationlocal variableName-- "Private" declaration - parsed the same waylocal _variableName
Variables in C#
string stringVariable = "value";// Public declarationpublic string variableName// Private declarationstring variableName;
Scope
In Luau, you can write variables and logic in a tighter scope than their function or class by nesting the logic within do and end keywords, similar to curly brackets {} in C#. For more details, see Scope.
Scoping in Luau
local outerVar = 'Outer scope text'do-- Modify 'outerVar'outerVar = 'Inner scope modified text'-- Introduce a local variablelocal innerVar = 'Inner scope text'print('1: ' .. outerVar) -- prints "1: Inner scope modified text"print('2: ' .. innerVar) -- prints "2: Inner scope text"endprint('3: ' .. outerVar) -- prints "3: "Inner scope modified text"-- Attempting to print 'innerVar' here would fail
Scoping in C#
var outerVar = "Outer scope text";{// Modify 'outerVar'outerVar = "Inner scope modified text";// Introduce a local variablevar innerVar = "Inner scope text";Console.WriteLine("1: " + outerVar); // prints "1: Inner scope modified text"Console.WriteLine("2: " + innerVar); // prints "2: Inner scope text"}Console.WriteLine("3: " + outerVar); // prints "3: "Inner scope modified text"// Attempting to print 'innerVar' here would fail
Conditional Statements
Conditional Statements in Luau
-- One conditionif boolExpression thendoSomething()end-- Multiple conditionsif not boolExpression thendoSomething()elseif otherBoolExpression thendoSomething()elsedoSomething()end
Conditional Statements in C#
// One conditionif (boolExpression) {doSomething();}// Multiple conditionsif (!boolExpression) {doSomething();}else if (otherBoolExpression) {doSomething();}else {doSomething();}
Conditional Operator
Conditional Operator in Luau
local max = if x > y then x else y
Conditional Operator in C#
int max = (x > y) ? x : y;
Loops
To learn more about loops in Luau, see Control Structures.
While and Repeat Loops
While and Repeat Loops in Luau
while boolExpression dodoSomething()endrepeatdoSomething()until not boolExpression
While and Repeat Loops in C#
while (boolExpression) {doSomething();}do {doSomething();} while (boolExpression)
For Loops
Generic For Loops in Luau
-- Forward loopfor i = 1, 10 dodoSomething()end-- Reverse loopfor i = 10, 1, -1 dodoSomething()end
Generic For Loops in C#
// Forward loopfor (int i = 1; i <= 10; i++) {doSomething();}// Reverse loopfor (int i = 10; i >= 1; i--) {doSomething();}
For Loops Over Tables in Luau
local abcList = {"a", "b", "c"}for i, v in ipairs(abcList) doprint(v)endlocal abcDictionary = { a=1, b=2, c=3 }for k, v in pairs(abcDictionary) doprint(k, v)end
For Loops Over Lists in C#
List<string> abcList = new List<string>{"a", "b", "c"};foreach (string v in abcList) {Console.WriteLine(v);}Dictionary<string, int> abcDictionary = new Dictionary<string, int>{ {"a", 1}, {"b", 2}, {"c", 3} };foreach (KeyValuePair<string, int> entry in abcDictionary) {Console.WriteLine(entry.Key + " " + entry.Value);}
Luau also supports generalized iteration, which further simplifies working with tables.
Functions
To learn more about functions in Luau, see Functions.
Generic Functions
Generic Functions in Luau
-- Generic function
local function increment(number)
return number + 1
end
Generic Functions in C#
// Generic function
int increment(int number) {
return number + 1;
}
Variable Argument Number
Variable Argument Number in Luau
-- Variable argument number
local function variableArguments(...)
print(...)
end
Variable Argument Number in C#
// Variable argument number
void variableArguments(params string[] inventoryItems) {
for (item in inventoryItems) {
Console.WriteLine(item);
}
}
Named Arguments
Named Arguments in Luau
-- Named arguments
local function namedArguments(args)
return args.name .. "'s birthday: " .. args.dob
end
namedArguments{name="Bob", dob="4/1/2000"}
Named Arguments in C#
// Named arguments
string namedArguments(string name, string dob) {
return name + "'s birthday: " + dob;
}
namedArguments(name: "Bob", dob: "4/1/2000");
Try-Catch Structures
Try/Catch Structures in Luau
local function fireWeapon()
if not weaponEquipped then
error("No weapon equipped!")
end
-- Proceed...
end
local success, errorMessage = pcall(fireWeapon)
if not success then
print(errorMessage)
end
Try/Catch Structures in C#
void fireWeapon() {
if (!weaponEquipped) {
// Use a user-defined exception
throw new InvalidWeaponException("No weapon equipped!");
}
// Proceed...
}
try {
fireWeapon();
} catch (InvalidWeaponException ex) {
// An error was raised
}