
为了应用你对模块脚本的知识,创建一个模块脚本,允许玩家拾取钥匙并利用它们打开宝箱。
项目设置
此项目包括一个起始地图,其中有排行榜和脚本化的拾取对象供钥匙和宝箱使用。
加载起始项目
在 Roblox Studio 中,打开下载的文件: Intro to Module Scripts - Starter Project.rbxl。

创建模块脚本
为了让玩家能够从宝箱中获取宝藏,创建一个名为 TreasureManager 的模块脚本。使用模块脚本将拾取对象和排行榜连接在一起。
在 ServerStorage 中,创建一个新的 ModuleScript 并将其重命名为 TreasureManager。

在 TreasureManager 中,将默认模块表的名称从 module 更改为 TreasureManager,在两个地方都修改。
local TreasureManager = {}return TreasureManager
在模块脚本中使用函数
要测试函数在模块脚本中的工作方式,创建一个名为 getKey() 的新函数。当从另一个脚本调用 getKey() 函数时,它将接收一个钥匙部件以销毁并将玩家库存中的钥匙数量增加 1。
为钥匙创建模块函数
此模块脚本将使用模块和本地函数的组合,请输入 两个 注释来帮助你将它们分开。
local TreasureManager = {}------------------ 本地函数------------------ 模块函数return TreasureManager在 模块函数 注释下,向 TreasureManager 添加一个名为 getKey() 的新模块函数。
使用两个参数:
- keyPart - 要销毁的部件。
- whichCharacter - 触碰钥匙部件的玩家。
local TreasureManager = {}------------------ 本地函数------------------ 模块函数function TreasureManager.getKey(keyPart, whichCharacter)endreturn TreasureManager在 getKey() 中,销毁 keyPart。
function TreasureManager.getKey(keyPart, whichCharacter)keyPart:Destroy()end
使用模块函数
现在,模块函数 getKey() 可以在其他脚本中使用。要测试该函数,你需要打开一个预制脚本并调用它。
打开 Workspace ⟩ Keys ⟩ KeyScript 中的钥匙脚本。
在 keyScript 中,将模块脚本存储在名为 treasureManager 的变量中,并将其设置为: require(ServerStorage:WaitForChild("TreasureManager"))
local ServerStorage = game:GetService("ServerStorage")-- 下面引入模块脚本 ⯆local treasureManager = require(ServerStorage:WaitForChild("TreasureManager"))local keys = script.Parentlocal keysFolder = keys.Partslocal keysArray = keysFolder:GetChildren()已经有一个名为 partTouched() 的函数用于检查玩家接触部件。在 partTouched() 中:
- 调用 getKey() 模块函数以销毁钥匙。
- 传入 keyPart 和 whichCharacter。
local ServerStorage = game:GetService("ServerStorage")-- 下面引入模块脚本 ⯆local treasureManager = require(ServerStorage:WaitForChild("TreasureManager"))local keys = script.Parentlocal keysFolder = keys.Partslocal keysArray = keysFolder:GetChildren()local function partTouched(otherPart, keyPart)local whichCharacter = otherPart.Parentlocal humanoid = whichCharacter:FindFirstChildWhichIsA("Humanoid")if humanoid then-- 给玩家一把钥匙并销毁钥匙部件-- =============================================treasureManager.getKey(keyPart, whichCharacter)-- =============================================endend运行项目并检查触碰钥匙是否能销毁它。
故障排除提示
问题: 获取一个错误消息,包括:"Infinite yield possible"。
- 检查你在脚本中模块脚本的拼写。如果模块脚本,如 TreasureManager 的拼写不正确,将会出现错误。
问题: 获取一个错误消息,包括:"attempt to index global"。
- 检查 keyScript 中包含要求的模块脚本的行。如果模块不包含要求,无法使用该模块脚本中的函数和变量。
问题: 脚本未运行或无法拾取钥匙。
在模块脚本中,请确保所有代码都在 local TreasureManager = {} 和 return TreasureManager 之间。返回必须是模块脚本代码的最后一行。
确保在要求行末尾有两个括号,如 WaitForChild("TreasureManager"))。
创建本地函数
现在,排行榜跟踪玩家的钥匙和宝藏数量。要更改排行榜数字,请在模块脚本中使用本地函数。使用本地函数是因为更改玩家的钥匙或宝藏值只需要在 TreasureManager 脚本中,而不是其他地方。
在 ServerStorage 中,打开 TreasureManager 脚本。
创建本地变量以执行以下操作:
获取 Players 服务,以便脚本可以处理玩家的排行榜统计信息。
存储玩家在接触 keyPart 后获得的钥匙数量。
local TreasureManager = {}local Players = game:GetService("Players")local keyDrop = 1------------------ 本地函数------------------ 模块函数function TreasureManager.getKey(keyPart, whichCharacter)keyPart:Destroy()endreturn TreasureManager将这两个本地函数复制并粘贴到 本地函数 部分。
getPlayerKeys() 返回玩家的 Lockpicks leaderboard 数值。
getPlayerTreasure() 返回玩家的 Treasure leaderboard 数值。
------------------ 本地函数local function getPlayerKeys(whichCharacter)local player = Players:GetPlayerFromCharacter(whichCharacter)local leaderstats = player:FindFirstChild("leaderstats")return leaderstats:WaitForChild("Lockpicks")endlocal function getPlayerTreasure(whichCharacter)local player = Players:GetPlayerFromCharacter(whichCharacter)local leaderstats = player:FindFirstChild("leaderstats")return leaderstats:WaitForChild("Treasure")end------------------ 模块函数在 getKey() 模块函数中,添加玩家钥匙的数量:
创建一个 local 变量来调用 getPlayerKeys(whichCharacter)。
将 keyDrop 的值加到 playerKeys 上。
------------------ 模块函数function TreasureManager.getKey(keyPart, whichCharacter)local playerKeys = getPlayerKeys(whichCharacter)playerKeys.Value = playerKeys.Value + keyDropkeyPart:Destroy()end运行项目。检查触碰钥匙是否能销毁它并向排行榜中的玩家钥匙增加 1。

如果需要,检查你的脚本与下面的脚本是否存在故障排除问题。
当前 TreasureManager 脚本
local TreasureManager = {}
local Players = game:GetService("Players")
local keyDrop = 1
------------------ 本地函数
local function getPlayerKeys(whichCharacter)
local player = Players:GetPlayerFromCharacter(whichCharacter)
local leaderstats = player:FindFirstChild("leaderstats")
return leaderstats:WaitForChild("Lockpicks")
end
local function getPlayerTreasure(whichCharacter)
local player = Players:GetPlayerFromCharacter(whichCharacter)
local leaderstats = player:FindFirstChild("leaderstats")
return leaderstats:WaitForChild("Treasure")
end
------------------ 模块函数
function TreasureManager.getKey(keyPart, whichCharacter)
local playerKeys = getPlayerKeys(whichCharacter)
playerKeys.Value = playerKeys.Value + keyDrop
keyPart:Destroy()
end
return TreasureManager
从模块脚本获取信息
TreasureManager 模块脚本将用于当玩家触碰宝箱时检查他们是否至少有一个钥匙,然后才能开启它并给予他们金子。
检查宝箱是否可以打开
首先在 ServerStorage ⟩ TreasureManager 脚本中设置用于打开宝箱所需钥匙的数量,以及每个宝箱包含的金子数量的变量。
local TreasureManager = {}local Players = game:GetService("Players")local keyDrop = 1local chestPickCost = 1local chestReward = 100------------------ 本地函数local function getPlayerKeys(whichCharacter)local player = Players:GetPlayerFromCharacter(whichCharacter)local leaderstats = player:FindFirstChild("leaderstats")return leaderstats:WaitForChild("Lockpicks")end为了创建一个检查玩家是否可以打开宝箱的函数,在 模块函数 部分,为 TreasureManager 表添加一个名为 canOpenChest() 的新函数,参数为 whichCharacter。
------------------ 模块函数function TreasureManager.canOpenChest(whichCharacter)endfunction TreasureManager.getKey(keyPart, whichCharacter)local playerKeys = getPlayerKeys(whichCharacter)playerKeys.Value = playerKeys.Value + keyDropkeyPart:Destroy()end将下面的代码复制并粘贴到 canOpenChest() 中,如果玩家有足够的钥匙则返回 true,否则返回 false。
function TreasureManager.canOpenChest(whichCharacter)local playerKeys = getPlayerKeys(whichCharacter)if playerKeys.Value >= chestPickCost thenreturn trueelsereturn falseendend
给予玩家宝藏
为了让玩家能够打开宝箱,在 TreasureManager 中创建一个函数来奖励他们宝藏。
向 TreasureManager 添加一个名为 openChest() 的新模块函数。
传入两个参数:
- chestPart - 要销毁的宝箱部件。
- whichCharacter - 要奖励宝藏的玩家。
function TreasureManager.openChest(chestPart, whichCharacter)end为了减少玩家的钥匙并奖励他们宝藏,将以下代码复制并粘贴到 openChest() 中。此代码使用之前创建的变量,例如每个宝箱给予的金子数量 chestReward。
function TreasureManager.openChest(chestPart, whichCharacter)local playerKeys = getPlayerKeys(whichCharacter)local playerTreasure = getPlayerTreasure(whichCharacter)playerKeys.Value = playerKeys.Value - chestPickCostplayerTreasure.Value = playerTreasure.Value + chestRewardchestPart.Parent:Destroy()end
调用宝箱函数
现在这两个模块函数 canOpenChest() 和 openChest() 已经创建,可以在玩家触碰宝箱时由宝箱部件调用,使用预制的 partTouched() 函数。
在 Workspace ⟩ Chests 中打开 ChestScript。
创建一个名为 treasureManager 的新变量,并在 ServerStorage 中引入 TreasureManager 模块脚本。
local ServerStorage = game:GetService("ServerStorage")-- 下面引入模块脚本local treasureManager = require(ServerStorage:WaitForChild("TreasureManager"))local chests = script.Parentlocal chestsFolder = chests.Partslocal chestsArray = chestsFolder:GetChildren()在 partTouched() 中,if humanoid 语句下,创建一个名为 canOpen 的新变量,并将其设置为:
treasureManager.canOpenChest(whichCharacter)
local function partTouched(otherPart, chestPart)local whichCharacter = otherPart.Parentlocal humanoid = whichCharacter:FindFirstChildWhichIsA("Humanoid")if humanoid then-- 检查玩家是否可以打开宝箱,然后让他们获得宝藏-- =============================================local canOpen = treasureManager.canOpenChest(whichCharacter)-- =============================================endend接下来,创建一个 if 语句以检查 canOpen 是否为 true。
如果是,调用 TreasureManager 的 openChest() 函数。
然后,传入两个参数:chestPart,即要销毁的宝箱,以及 whichCharacter,即所奖励宝藏的玩家。
local function partTouched(otherPart, chestPart)local whichCharacter = otherPart.Parentlocal humanoid = whichCharacter:FindFirstChildWhichIsA("Humanoid")if humanoid then-- 检查玩家是否可以打开宝箱,然后让他们获得宝藏-- =============================================local canOpen = treasureManager.canOpenChest(whichCharacter)if canOpen == true thentreasureManager.openChest(chestPart, whichCharacter)end-- =============================================endend运行项目。检查:
- 如果你拥有至少 1 把钥匙,触碰宝箱将会摧毁它并给予宝藏。
- 如果你没有钥匙,则无法打开宝箱。
故障排除提示
在 ChestScript 中,请确保从模块脚本调用的函数,如 canOpenChest(),拼写与 TreasureManager 脚本中的名称完全相同。任何差异都会导致错误。
检查复印和粘贴的函数,如 treasureManager.openChest(),是否与课件中显示的完全一致。任何差异可能在脚本中引起细微错误。
完成的脚本
完成的 TreasureManager 脚本
local TreasureManager = {}
local Players = game:GetService("Players")
local keyDrop = 1
local chestPickCost = 1
local chestReward = 100
------------------ 本地函数
local function getPlayerKeys(whichCharacter)
local player = Players:GetPlayerFromCharacter(whichCharacter)
local leaderstats = player:FindFirstChild("leaderstats")
return leaderstats:WaitForChild("Lockpicks")
end
local function getPlayerTreasure(whichCharacter)
local player = Players:GetPlayerFromCharacter(whichCharacter)
local leaderstats = player:FindFirstChild("leaderstats")
return leaderstats:WaitForChild("Treasure")
end
------------------ 模块函数
function TreasureManager.openChest(chestPart, whichCharacter)
local playerKeys = getPlayerKeys(whichCharacter)
local playerTreasure = getPlayerTreasure(whichCharacter)
playerKeys.Value = playerKeys.Value - chestPickCost
playerTreasure.Value = playerTreasure.Value + chestReward
chestPart.Parent:Destroy()
end
function TreasureManager.canOpenChest(whichCharacter)
local playerKeys = getPlayerKeys(whichCharacter)
if playerKeys.Value >= chestPickCost then
return true
else
return false
end
end
function TreasureManager.getKey(keyPart, whichCharacter)
local playerKeys = getPlayerKeys(whichCharacter)
playerKeys.Value = playerKeys.Value + keyDrop
keyPart:Destroy()
end
return TreasureManager
完成的 ChestScript
local ServerStorage = game:GetService("ServerStorage")
-- 下面引入模块脚本 ⯆
local treasureManager = require(ServerStorage:WaitForChild("TreasureManager"))
local chests = script.Parent
local chestsFolder = chests.Parts
local chestsArray = chestsFolder:GetChildren()
local function partTouched(otherPart, chestPart)
local whichCharacter = otherPart.Parent
local humanoid = whichCharacter:FindFirstChildWhichIsA("Humanoid")
if humanoid then
-- 检查玩家是否可以打开宝箱,然后让他们获得宝藏
-- =============================================
local canOpen = treasureManager.canOpenChest(whichCharacter)
if canOpen == true then
treasureManager.openChest(chestPart, whichCharacter)
end
-- =============================================
end
end
-- 将每个宝箱部件绑定到触碰函数,以便在所有部件上都能工作
for chestIndex = 1, #chestsArray do
local chestPart = chestsArray[chestIndex]:WaitForChild("Collider")
chestPart.Touched:Connect(function(otherPart)
partTouched(otherPart, chestPart)
end)
end
完成的 keyScript
local ServerStorage = game:GetService("ServerStorage")
-- 下面引入模块脚本 ⯆
local treasureManager = require(ServerStorage:WaitForChild("TreasureManager"))
local keys = script.Parent
local keysFolder = keys.Parts
local keysArray = keysFolder:GetChildren()
local function partTouched(otherPart, keyPart)
local whichCharacter = otherPart.Parent
local humanoid = whichCharacter:FindFirstChildWhichIsA("Humanoid")
if humanoid then
-- 给玩家一把钥匙并销毁钥匙部件
-- =============================================
treasureManager.getKey(keyPart, whichCharacter)
-- =============================================
end
end
-- 将每个钥匙部件绑定到触碰函数,以便在所有部件上都能工作
for keyIndex = 1, #keysArray do
local keyPart = keysArray[keyIndex]
keyPart.Touched:Connect(function(otherPart)
partTouched(otherPart, keyPart)
end)
end
总结
在 Roblox 体验中使用模块脚本的一种常见应用是处理玩家使用的常见任务,例如给予他们积分。在本例中,创建了一个名为 TreasureManager 的模块脚本,以处理每当玩家与游戏对象交互时给予他们钥匙和宝藏的功能。