This project makes use of Luacheck for catching common mistakes. Install it and configure it for your text editor.
We recommend Atom for editing Lua code along with the following packages:
- linter-luacheck: Luacheck integration
- defold-ide: Defold API autocompletion (automatically installs language-lua and autocomplete-lua)
- language-lua: Syntax highlighting
- autocomplete-lua: Autocomplete
-
Don't use semicolons
-- DO: print("hello") -- DON'T: print("hello");
-
Use 2 spaces for indentation. No tabs.
-- DO: if a > 0 then print("hello") end -- DON'T: if a > 0 then print("hello") end
-
Use double quotes for string literals
-- DO: print("Hello world!") -- DON'T: print('Hello world!')
-
Use spaces between binary operators and operands
-- DO: return a + b -- DON'T: return a+b
-
Don't add spaces between
-
,#
unary operators and operands-- DO: local question_count = #questions local minus_x = -x -- DON'T: local question_count = # questions local minus_x = - x
-
Don't pad parentheses with spaces
-- DO: my_function(a, b, c) return (a + b) * c -- DON'T: my_function( a, b, c ) return ( a + b ) * c
-
Don't add spaces before
(
in function calls or definitions-- DO: function my_function(a, b) my_other_function(a, b) end -- DON'T: function my_function (a, b) my_other_function (a, b) end
-
Start comments with a space
-- DO --DON'T
-
Use meaningful names for variables, functions, arguments, fields and other things.
Try to avoid abbreviations. Single letter variables are only allowed for indices (
i
,j
, etc.) and coordinates (x
,y
,z
,t
, etc.).-- DO: local position = get_player_position() local distance_from_origin = math.sqrt(position.x * position.x + position.y * position.y) -- DON'T: local a = f() local b = math.sqrt(a.x * a.x + a.y * a.y)
-
Use
snake_case
for variable, args, function and field names.-- DO: local my_variable local my_other_variable function my_function() end -- DON'T: local myVariable local MyOtherVariable function mY_fUncTion() end
-
Use
UpperCamelCase
for class names.-- DO: local Button = { __index = {} } function Button.__index:some_method() end
-
Use
MACRO_CASE
for enumeration constants.-- DO: local STATE_IDLE = 1 local STATE_PRESSED_DOWN = 2 local STATE_HOVERED = 3
-
Use .0 for float number literals
Lua's number type makes no difference between
2
and2.0
, but it helps to visually annotate numbers as floats or integers depending on their usage.-- DO: local new_x = x * 2.0 -- coordinates are float local next_index = index + 1 -- indices are integer -- DON'T: local new_x = x * 2 local next_index = index + 1.0
-
No unused variables except unused function arguments
Luacheck will yell at you for this.
-- DON'T: function my_function() local something = some_function() -- the value in something never gets used end -- Acceptable: function transform_coordinates(x, y) return x * 2.0, 0.0 end
-
Separate logical blocks with single blank lines
What counts as a logical block is up to you, but try to avoid 30-line-long blocks of code with no visual structure. Don't use more than one blank line!
-- DO: local last_animation = self.blink_last_animation or 1 local repeat_count = self.blink_repeat_count or 0 local fear_treshold = subject.idle_animation_fear_treshold local next_animation if repeat_count >= (last_animation == 1 and 1 or 5) then next_animation = 3 - last_animation else next_animation = math.random(2) end
-
Pre-calculate constant hashes and game object IDs
Hashing and accessing game objects by their string URL is an O(n) operation. Pre-calculate hashes to avoid creating them in performance-sensitive code.
-- DO: local h_scene_init = hash("scene_init") function on_message(self, message_id, message) if message_id == h_scene_init then -- Do stuff end end -- DON'T: function on_message(self, message_id, message) if message_id == hash("scene_init") then -- Do stuff end end