函数是代码块,您可以按命令多次执行它们。您还可以将它们连接到事件或将它们指定为回调。
基本函数
函数定义包括:
- 函数的作用域(全局或local)。
- 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
方法
方法是对象的函数,例如类或表。它们期望对象本身(self)作为第一个参数。当您调用方法时,使用冒号符号(:)而不是点符号(.)来自动传递self作为第一个参数。
Roblox中的所有对象都源自Instance,并拥有常用的方法,包括Instance:Destroy()、Instance:Clone()和Instance:FindFirstChild()。
local Workspace = game:GetService("Workspace")-- 使用点符号(函数)销毁一个部件local firstPart = Instance.new("Part")firstPart.Parent = Workspaceprint(firstPart.Parent) -- WorkspacefirstPart.Destroy(firstPart)print(firstPart.Parent) -- nil-- 使用冒号符号(方法)销毁一个部件local secondPart = Instance.new("Part")secondPart.Parent = Workspaceprint(secondPart.Parent) -- WorkspacesecondPart: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 = 4print(string.format("The %s is a %s!", "cake", "lie")) -- The cake is a lie!print(string.char(115, 101, 99, 114, 101, 116)) -- secret
定义变参函数
要定义变参函数,您可以将...标记用作最后一个或唯一参数(不要与..这个连接运算符混淆)。您可以将...值放入表中以便于使用。
local function variadic(named, ...)
local arguments = {...} -- 将额外的参数打包成一个表
print("Named argument =", named)
for i, value in arguments do
print("Input No.", i, "=", value)
end
end
variadic(10, "Hi", 20, "Variadic Function")
--[[ 结果输出:
Named argument = 10
Input No. 1 = Hi
Input No. 2 = 20
Input No. 3 = Variadic Function
]]
转发参数
您可以将变参函数定义为其他函数的包装器,以便将参数从包装器传递或转发到其他函数。
local function printAround(functionToPrintAround, ...)
print("Before")
functionToPrintAround(...)
print("After")
end
local function addNumbers(x, y, z)
print("x =", x)
print("y + z =", y + z)
end
printAround(addNumbers, 1, 2, 3)
--[[ 结果输出:
Before
x = 1
y + z = 5
After
]]
使用数组调用变参函数
如果您想将值的表数组传递给全局变参函数,例如print(),您可以使用全局unpack()函数传递表的值,而不是表本身。
local squares = {1, 4, 9, 16, 25}print("前5个平方数是:", unpack(squares))-- 前5个平方数是 1 4 9 16 25