函数是代码块,您可以根据命令多次执行它们。您还可以将它们连接到事件或将它们指定为回调。
基本函数
函数定义包括:
- function关键字。
- 函数的名称采用camelCase格式。
- 函数的参数用括号(())括起来。
- 函数的代码块或“主体”。
- end关键字。
当您调用函数时,函数的主体会执行。要调用函数,请输入其名称后跟括号。您可以定义一个变量来接收返回值,或在变量的位置使用返回值。
-- 这个函数没有参数,返回nil
local function addOneAndTwo()
local result = 1 + 2
print(result)
end
-- 调用一个没有返回值的函数
addOneAndTwo() -- 3参数
参数是您提供给函数的变量,仅在函数的作用域中使用。默认情况下,函数没有参数。如果您用比函数预期的更多参数调用函数,Luau会忽略额外的参数。如果您用比函数预期的更少参数调用函数,Luau会为所有缺失的参数传递nil。
-- 这个函数有两个参数:num1和num2
local function addNumbers(num1, num2)
print(num1 + num2)
end
addNumbers(2, 3) -- 5
addNumbers(5, 6, 7) -- 11
addNumbers(9) -- 尝试对数字和nil进行算术运算(加法)返回
在函数的主体中,return关键字从计算中返回结果。您可以从一个函数返回多个值。return结束函数执行,Luau期望end关键字跟随return语句,因此在return命令和end命令之间编写代码会引发错误。
-- 这个函数返回一个返回值
local function addNumbers(num1, num2)
local result = num1 + num2
return result
end
print(addNumbers(1, 2)) -- 3
local seven = addNumbers(3, 4)
print(seven) -- 7
-- 这个函数返回多个值:和与差
local function addAndSubtract(num1, num2)
local sum = num1 + num2
local difference = num1 - num2
return sum, difference
end
-- 调用一个函数并期望多个返回值
local sum, difference = addAndSubtract(2, 3)
print(sum) -- 5
print(difference) -- -1方法
方法是对象的函数,例如class或表。它们期望对象本身(self)作为第一个参数。当您调用方法时,请使用冒号符号(:)而不是点符号(.)来自动将self作为第一个参数传递。
Roblox中的所有对象都继承自Instance,并具有常用的方法,包括Instance:Destroy()、Instance:Clone()和Instance:FindFirstChild()。
local Workspace = game:GetService("Workspace")
-- 使用点符号(函数)销毁一个部件
local firstPart = Instance.new("Part")
firstPart.Parent = Workspace
print(firstPart.Parent) -- Workspace
firstPart.Destroy(firstPart)
print(firstPart.Parent) -- nil
-- 使用冒号符号(方法)销毁一个部件
local secondPart = Instance.new("Part")
secondPart.Parent = Workspace
print(secondPart.Parent) -- Workspace
secondPart:Destroy()
print(secondPart.Parent) -- nil定义方法
要在表中创建方法,请使用方法的名称作为键,方法函数作为值。在方法的定义中,self参数指的是方法的父表。当您使用冒号符号调用方法时,您将表本身作为第一个参数传递。您可以为方法定义参数,但需要在self参数之后列出它们。
在以下示例中,testButton表的changeEnabled键的值是一个方法。您可以通过打印self.enabled的值来验证self指的是方法的父表。
local testButton = {
enabled = true,
changeEnabled = function(self, isEnabled)
self.enabled = isEnabled
print(self.enabled)
end
}
print(testButton.enabled) -- true
-- 调用方法
testButton:changeEnabled(false) -- false回调
回调是响应另一个函数或过程执行的函数。
基本回调
函数可以传递给其他函数,例如,可以使用匿名函数来实现一个回调,table.sort()然后使用该回调对Players的列表进行排序,列表来自Players.GetPlayers()。
local Players = game:GetService("Players")
local sortedPlayers = Players:GetPlayers()
table.sort(sortedPlayers, function(a, b)
-- 使用匿名回调按名称排序玩家
return a.Name < b.Name
end)在Roblox API中,回调指的是一个只写的函数成员,回调会在返回之前挂起。广泛使用的回调包括:
- MarketplaceService.ProcessReceipt,处理开发者产品购买。
- BindableFunction.OnInvoke,当脚本调用BindableFunction:Invoke(...)时调用该函数。
- RemoteFunction.OnClientInvoke,当服务器调用RemoteFunction:FireClient(player, ...)或RemoteFunction:FireAllClients(...)时调用该函数。
- RemoteFunction.OnServerInvoke,当客户端调用RemoteFunction:InvokeServer(...)时调用该函数。
要设置回调,请将函数分配给它。例如,BindableFunction.OnInvoke是BindableFunction的回调。您可以将命名或匿名函数设置为它,并且可以通过调用回调上的:Invoke()方法来调用(调用)该函数。您传递给:Invoke()的参数会转发到回调中,回调函数的返回值会返回给:Invoke()的调用者。
local bindableFunction = Instance.new("BindableFunction")
bindableFunction.OnInvoke = function(number)
return 2 * number
end
print(bindableFunction:Invoke(42)) -- 84函数技巧
事件处理程序
您可以分配一个称为事件处理程序的函数,在事件触发时执行。例如,您可以创建一个名为onPlayerAdded()的函数,连接到Players.PlayerAdded事件,以打印任何加入的玩家的名称。有关更多信息,请参见事件。
local Players = game:GetService("Players")
local function onPlayerAdded(player)
print(player.Name .. " 加入了游戏!")
end
Players.PlayerAdded:Connect(onPlayerAdded)匿名函数
您可以创建没有名称的函数,称为匿名函数,用于作为回调和事件处理程序。与命名函数一样,匿名函数需要以function和end关键字开始和结束,但您不需要使用local关键字来指示局部作用域,因为它们总是具有局部作用域。
在以下示例中,task.delay()函数的回调和Players.PlayerAdded事件的事件处理程序都是匿名函数。
-- 在回调中使用匿名函数调用task.delay()
task.delay(2, function(exactTimeElapsed)
print(exactTimeElapsed) -- 2.0064592329945
end)
-- 在事件处理程序中使用匿名函数
local Players = game:GetService("Players")
Players.PlayerAdded:Connect(function(player)
print(player.Name .. " 加入了游戏!")
end)模块脚本中的函数
您可以通过将函数存储在ModuleScripts中,在多个脚本之间重用函数。函数是Luau数据类型,因此您可以将它们与其他数据一起存储在表中。
可变参数函数
可变参数函数接受任意数量的参数。例如,Globals.LuaGlobals.print()是一个可变参数函数。
print(2, "+", 2, "=", 2 + 2) --2 + 2 = 4
print(string.format("这个 %s 是一个 %s!", "蛋糕", "谎言")) -- 这个蛋糕是一个谎言!
print(string.char(115, 101, 99, 114, 101, 116)) -- secret定义可变参数函数
要定义可变参数函数,您可以使用...标记作为最后一个或唯一参数(不要与..,连接运算符混淆)。您可以将...值放入表中以便于使用。
local function variadic(named, ...)
local arguments = {...} -- 将额外参数打包到表中
print("命名参数 =", named)
for i, value in arguments do
print("输入编号.", i, "=", value)
end
end
variadic(10, "嗨", 20, "可变参数函数")
--[[ 结果输出:
命名参数 = 10
输入编号. 1 = 嗨
输入编号. 2 = 20
输入编号. 3 = 可变参数函数
]]转发参数
您可以将可变参数函数定义为其他函数的包装器,以传递或转发参数,从包装器到其他函数。
local function printAround(functionToPrintAround, ...)
print("之前")
functionToPrintAround(...)
print("之后")
end
local function addNumbers(x, y, z)
print("x =", x)
print("y + z =", y + z)
end
printAround(addNumbers, 1, 2, 3)
--[[ 结果输出:
之前
x = 1
y + z = 5
之后
]]使用数组调用可变参数函数
如果您想将值的表数组传递给全局可变参数函数,例如print(),您可以使用全局unpack()函数传递表的值,而不是表本身。
local squares = {1, 4, 9, 16, 25}
print("前5个平方数是:", unpack(squares))
-- 前5个平方数是 1 4 9 16 25