As we’ve seen, functions can take argument inputs that will then perform its task based on the inputs.
To create a function that can accept arguments, you first have to define parameters to reference each argument input.
Parameters are little more than local variables and obey the same variable naming rules. Because they are local to the function, parameters are available to nested statements and deallocated after the function returns.
local function printSumAndDifference(firstNumber, secondNumber)
print(firstNumber + secondNumber, firstNumber - secondNumber)
end
printSumAndDifference(3.14, 42) --Output: 45.14 -38.86
Returning to our part creation routine, we can abstract the code into a function that takes the position and color as the argument.
local function createPart(position, color)
local part = Instance.new("Part")
part.Position = position
part.BrickColor = color
part.Anchored = true
part.Shape = Enum.PartType.Cylinder
part.Parent = game.Workspace
end
createPart(Vector3.new(1, 2, 3), BrickColor.new("Hot pink"))
Default Arguments
Earlier we also encountered functions and methods that do not necessarily require an argument—such as Vector3 or CFrame.
local v3_1 = Vector3.new() --Position: 0, 0, 0
local v3_2 = Vector3.new(1, 2, 3) --Position: 1, 2, 3
This is possible because behind the scenes (and at a “lower” level), these functions have preset values that are automatically assigned if no argument is specified. This is called a default argument.
Lua does not have support for default arguments, however, we can emulate a similar behavior using a conditional statement.
local function createPart(position, color)
local part = Instance.new("Part")
part.BrickColor = color or BrickColor.new("Lime green")
part.Position = position or Vector3.new()
part.Anchored = true
part.CanCollide = false
part.Shape = Enum.PartType.Ball
part.Parent = game.Workspace
end
createPart(Vector3.new(1, 5, 3))
createPart(Vector3.new(-1, 5, -3), BrickColor.new("Hot pink"))
On lines 3 and 4, the conditional check determines if the color or position were given and applies a pre-defined value if those are missing. Now when we call this function and do not provide an argument, the default color will be assigned to the part.
Let’s use it to create a slightly different program.
This time we’ll create a fire at the position of the player’s foot at regular time intervals, leaving a trail of fire as they traverse the map. We’ll also set a different fire color for each foot.
local Players = game:GetService("Players")
local Debris = game:GetService("Debris")
local function createFire(parent, color)
local fire = Instance.new("Fire")
fire.Color = color
fire.SecondaryColor = Color3.new(1, 1, 1)
fire.Size = 2
fire.Parent = parent
end
local function createPart(position, brickColor)
local part = Instance.new("Part")
part.BrickColor = brickColor or BrickColor.new("Lime green")
part.Position = position
part.Anchored = true
part.CanCollide = false
part.Transparency = 1
part.Parent = game.Workspace
createFire(part, part.BrickColor.Color)
Debris:AddItem(part, 3)
end
while true do
currentPlayers = Players:GetChildren()
for _, player in ipairs(currentPlayers) do
if player.Character then
local rightFootPosition = player.Character.LeftFoot.Position
local leftFootPosition = player.Character.RightFoot.Position
createPart(rightFootPosition, BrickColor.new("Deep orange"))
createPart(leftFootPosition)
end
end
task.wait(0.1)
end
When a player enters the game, the player object is created but not yet assigned a character. The if statement checks that the character exists (truthy) before attempting to run the statement.
The Debris service is one we have not encountered yet. This service has a single method, AddItem, which schedules the object for cleanup after the given time.
‘Fire‘ is a Roblox built-in class that simulates a flame. Since this needs to be parented to a part (or ‘Attachment’), we assign it to the part.
When writing a function, the general guideline is to aim for a function that only does “one thing” and give it a name that describes that task.
The print function, for instance, does one thing and has a properly descriptive variable name. On the other hand, if a function was named getItemPrice but returns the price after applying discounts, it does not do one thing and the name is now inaccurate because you might be expecting an item price but instead get a modified price.
This also keeps your functions short. Functions may call other functions but anything under about 20 lines of code is ideal. Oftentimes a lot less.