重複使用代碼

*此內容是使用 AI(Beta 測試版)翻譯,可能含有錯誤。若要以英文檢視此頁面,請按一下這裡

創建了幾個腳本之後,在你想要重複使用它們之間的代碼之前,從來沒有那麼久。取決於 位置ModuleScripts讓您在客戶端服務器邊界或同一邊界上的不同側面之間重複使用代碼。

您可以將模組腳本放在任何你放置腳本的地方,但 ReplicatedStorage 是一個常見位置;在此儲存模組腳本可讓您在服務器和客戶端之間重複使用代碼。

模組腳本的結指令碼

在 Roblox Studio 中,將模組腳本添加到 ReplicatedStorage 並重命名為 PickupManager 。每個 ModuleScript 以下代碼開始:


local module = {}
return module

這段代碼創建一個空的 Luau ,並將其返回到任何需要模組腳本的腳指令碼。

返回值可以是任何 數據類型 除了 nil 之外,但大多數模組腳本返回一個函數、一個表或一組功能表。為了生成其返回值,模組腳本當然可以執行任意代碼,其中包括需要其他模組腳本。

以下範例返回一個包含單一功能的表 getPickupBonus 。將它貼到新模組腳指令碼中:


-- 複製儲存中的模組腳本
local PickupManager = {}
local defaultMultiplier = 1.25
local rarityMultipliers = {
common = 10,
uncommon = 20,
rare = 50,
legendary = 100
}
-- 將 getPickupBonus 功能添加到 PickupManager 表
PickupManager.getPickupBonus = function(rarity)
local bonus = rarityMultipliers[rarity] * defaultMultiplier
return bonus
end
return PickupManager

將功能添加到表不一定是必要的——你只需要返回功能本身即可——但這是一個很好的模式;當你從其他腳本呼叫功能時,你會得到易於理解的語法;當你隨著時間的推移逐漸添加更多功能到模組腳本時,它也會給你一個容易理解的模式。

需要模組腳本

要載入模組腳指令碼,您可以呼叫 require() 功能。在 ReplicatedStorage 中,添加新的腳指令碼,並將其 RunContext 變更為 Client 。然後添加以下代碼來呼叫 PickupManager.getPickupBonus 函數:

複製儲存中的客戶端腳本

local ReplicatedStorage = game:GetService("ReplicatedStorage")
-- 取得模組腳本返回的值
local PickupManager = require(ReplicatedStorage:WaitForChild("PickupManager"))
-- 呼叫模組化功能
local bonus = PickupManager.getPickupBonus("legendary")
print(bonus) --> 125

將模組腳本存儲在 ReplicatedStorage 中,可以讓您在服務器和客戶端之間共享代碼,因此您可以使用相同的代碼要求從 ServerScriptService 中的腳本:

服務器腳本服務中的腳本

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local PickupManager = require(ReplicatedStorage:WaitForChild("PickupManager"))

當您在 require() 上呼叫 ModuleScript 時,會執行一次並返回一個單一項目作為參考。再次呼叫 require() 返回相同的參考,即如果您修改返回的 Instance ,後續的 require() 呼叫將返回該修改參考。模組本身不會多次運行。

如果您需要從客戶端服務器邊界的兩側獲得 ModuleScript,例如上面的示例,那麼 ModuleScript 將為每一側返回獨特的參考。

模式

模組腳本有一些常見模式,您可以使用它們來簡化代碼,避免隨著經驗規模和複雜度增長而出現問題。

數據共享

若要將資料與個別對象聯繫,您可以為它們指定特性或創建 Configuration 夾子值對象,例如 StringValueIntValue 。然而,如果您想添加或修改數十個物件或數據值,兩種方法都很麻煩。它們也不儲存表或功能。

如果您想修改相同對象的多個副本的相同數據或重複使用相同數據以對不同對象進行重複,請將數據存儲在 ModuleScripts 中。這是一個讓你更容易在其他腳本中重複使用資料的方法,你也可以儲存表和功能。

下面的例子 ModuleScriptReplicatedStorage 中儲存了通用槍的配置值:

複製儲存中的模組腳本

local GunConfig = {}
GunConfig.MagazineSize = 20
GunConfig.AmmoCount = 100
GunConfig.Firerate = 600
GunConfig.Damage = {
["Head"] = 50;
["Torso"] = 40;
["Body"] = 25;
}
return GunConfig

自訂事件

自訂事件讓腳本之間通訊,但必須跟蹤個別 BindableEvent 對象的參考可能會凌亂您的代碼。

您可以使用 ModuleScripts 來儲存 BindableEvents 並提供與 ModuleScript 方法直接相關的自訂事件處理程序。

下列 ModuleScriptReplicatedStorage 中有一個自訂事件,當開關變更狀態時發生:

複製儲存中的模組腳本

local Switch = {}
-- 創建可綁定的方式,因此任何腳本都可以聆聽交換器變更時
local bindableEvent = Instance.new("BindableEvent")
Switch.Changed = bindableEvent.Event
local state = false
function Switch.flip()
state = not state
bindableEvent:Fire(state)
end
return Switch

下列客戶端腳本在 ReplicatedStorage 連接一個功能,在 Switch.Changed 事件發生時呼叫。

複製儲存中的腳本

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Switch = require(ReplicatedStorage:WaitForChild("Switch"))
Switch.Changed:Connect(function(newState)
print("Switch state is now", newState)
end
-- 測試翻轉幾次
task.wait(1)
Switch.flip()
task.wait(1)
Switch.flip()

封裝

封裝是創建對象或腳本邏輯周圍的抽象層以隱藏複雜性的做法。您可以使用 ModuleScripts 將 Roblox 對象用自訂 Luau 功能封裝,以簡化代碼。

例如,你可以使用封裝來:

  • 使用單一 RemoteEvent 物件簡化跨網絡通信。
  • 將錯誤處理代碼包圍敏感服務,例如 DataStoreService
  • 定義自訂方法來控制或擴展 Roblox 對象功能。

跟蹤數十個單獨的 RemoteEvent 物件來實現遊戲中的網路很困難。您可以使用 ModuleScript 來封裝單個 RemoteEvent 來幫助簡化此問題。通過包含獨特的 參引數,您仍然可以使用單個 傳送不同的網絡訊息,而只使用單個 。

以下示例中, 命名為 的方法包含了額外的 參數。此外,這 ModuleScript 參考 RemoteEvent 引數象本身,因此您不需要在其他部分的代碼中參考它。您只需要要求此 ModuleScript 發送網絡消息,並不需要處理您代碼庫中剩下的 RemoteEvent 對象。

下列 ModuleScriptReplicatedFirst 提供了一個封裝的功能,您可以呼叫客戶端腳本發送網絡訊息:

網路模組

-- 複製第一個名為 NetworkManagerClient 的模組腳本
local NetworkManagerClient = {}
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local remoteEvent = ReplicatedStorage:WaitForChild("RemoteEvent")
-- 封裝遠端對物件的 FireServer 功能
function NetworkManagerClient.FireServer(id, ...)
remoteEvent:FireServer(id, ...)
end
return NetworkManagerClient

下列 ModuleScriptServerScriptService 使用 BindableEvents 為每個腳本連接到特定的ID。當客戶端發送網絡訊息時,每個 BindableEvent 與指定的ID相關的火災發生。


-- 名為 NetworkManagerServer 的 ServerScript 服務中的模組腳本
local NetworkManagerServer = {}
local networkSignalList = {}
function NetworkManagerServer.GetServerEventSignal(id)
local bindableEvent = Instance.new("BindableEvent")
-- 將新的可綁定事件連結到 id
table.insert(networkSignalList, {
id = id,
bindableEvent = bindableEvent,
})
return bindableEvent.Event
end
-- 連接到
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local remoteEvent = ReplicatedStorage:WaitForChild("RemoteEvent")
remoteEvent.OnServerEvent:Connect(function(player, id, ...)
-- 找到符合接收到的遠端事件ID的所有可綁定事件
for _, signal in networkSignalList do
if signal.id == id then
signal.bindableEvent:Fire(player, ...)
end
end
end)
return NetworkManagerServer

下列 LocalScript 發送一個具有ID RequestA 的消息,並帶有可選的Hello引數。


-- 在 ReplicatedFirst 中的本地腳本
local ReplicatedFirst = game:GetService("ReplicatedFirst")
local NetworkManagerClient = require(ReplicatedFirst:WaitForChild("NetworkManagerClient"))
NetworkManagerClient.FireServer("RequestA", "Hello")

下列 Script 連接到網絡訊息ID RequestA 並在收到請邀請時打印包含任何額外參數的聲明。


-- 服務器腳本服務中的腳本
local ServerScriptService = game:GetService("ServerScriptService")
local NetworkManagerServer = require(ServerScriptService:WaitForChild("NetworkManagerServer"))
NetworkManagerServer.GetServerEventSignal("RequestA"):Connect(function(player, ...)
print("Received RequestA from", player, ...)
end)