創建幾個指令碼後,在幾個指令碼之間,你的代碼不會長久。在 位置 上, ModuleScripts 可以在不同邊緣的客戶端/服務器邊緣之間重用代碼。
建立模組指令碼
您可以將模組指令放在任何您放置模組的地方,但 ReplicatedStorage 是一個流行的位置;將模組指令存儲在這裡,您可以在服務器和客戶端之間重用代碼。
- 在 Roblox Studio 中,在 Explorer 窗口中移動 ReplicatedStorage 並單擊 +。
- 選擇 ModuleScript 以添加新模組腳指令碼。
- 右鍵點擊腳本並將其重命名為 PickupManager。
- 雙擊腳本以在 腳本編輯器 中打開。
模組腳本的解剖
每個 ModuleScript 以下代碼開始:
local module = {}return module
此代碼會建立一個空 Luau 表 並將其返回任何需要模組指指令碼的指令。
返回值可以是任何 資料類型 除了 nil 之外,但大多數模組指令碼都會返回一個函數、表或表。要生成其返回值,模組指令碼可以當然運行任意代碼、表或表。
下列示例將返回一個包含單個功能為 getPickupBonus 的表。將它貼入到您的新模組指令碼中:
-- ReplicatedStorage 中的模組脚本
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 為 1> Client 。 然後添加以下代碼來呼叫4> PickupManager.getPickupBonus4> 功
ReplicatedStorage 中的客戶端指令碼
local ReplicatedStorage = game:GetService("ReplicatedStorage")-- 取得ModuleScript的值local PickupManager = require(ReplicatedStorage:WaitForChild("PickupManager"))-- 呼叫模組腳本功能local bonus = PickupManager.getPickupBonus("legendary")print(bonus) --> 125
您可以使用相同的代碼來要求 ServerScriptService 的脚本:
ServerScriptStorage 中的脚本
local ReplicatedStorage = game:GetService("ReplicatedStorage")-- 取得 "PickupManager" 模組指定的 "輸入模組" 的返回值local PickupManager = require(ReplicatedStorage:WaitForChild("PickupManager"))
當您在 require() 上呼叫 ModuleScript 時,它會執行一次並作為引用返回一個單一項目。再次呼叫 Global.LuaGlobals.requir需要 必填()</
如果您需要從客戶端-伺服器兩側的 ModuleScript,則 ModuleScript 會返回每個側面的唯一引用。
模式
模組腳本具有一些常見模式,您可以使用它們來簡化您的代碼,並避免隨著您的體驗尺寸和複雜性增長而導致的陷阱。
資料共享
要將資料與個別對象關聯,您可以為其分配屬性或創建 Configuration 文件夾以值對象(例如 StringValue 或 IntValue)。然而,如果您想要添加或修改十個以上對象或資料值,這兩種方法都很麻煩。它們也不儲存桌子或函
如果您想為同一個對象複製多個副本,或者重用相同的資料,存儲資料在 ModuleScripts 中。這是一種更簡單的方式來在其他指令碼中重用資料,並且您可以存儲表和函數。
在 ModuleScript 中的 ReplicatedStorage 存儲了一些通用槍的設定值:
ReplicatedStorage 中的模組脚本
local GunConfig = {}GunConfig.MagazineSize = 20GunConfig.AmmoCount = 100GunConfig.Firerate = 600GunConfig.Damage = {["Head"] = 50;["Torso"] = 40;["Body"] = 25;}return GunConfig
自訂事件
自訂事件讓指令碼能與其他指令碼通信,但必須跟蹤指向個別 BindableEvent 對象的引用,才能使您的代碼凌亂。
您可以使用 ModuleScripts 來存儲 BindableEvents 並提供與 ModuleScript 方法直接相關的自訂事件處理程式。
Class.ReplicatedStorage|ReplicatedStorage 中的 ReplicatedStorage 有一個自訂事件,當開關變更狀態時發生:
ReplicatedStorage 中的模組脚本
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 事件發生時呼叫。
ReplicatedStorage 中的脚本
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 對象以自訂 Lua 函數封裝來簡化代碼。
舉例來說,你可以使用帶膠囊化的方法來:
- 使用單個 RemoteEvent 對物件簡化網路通訊。
- 將錯誤處理程式碼包圍敏感服務,例如 DataStoreService。
- 定義自訂方法來控制或擴展 Roblox 物件功能。
追蹤數十個獨立的 RemoteEvent 對象來實現網路在您的遊戲中的實現是很困難的。您可以使用 ModuleScript 來帶虛擬網路的實現進行封裝,以幫助簡化此問題。 通
下面的例子中,名為 NetworkManagerClient 的 RemoteEvent:FireServer() 包裹了 <
Class.ReplicatedFirst 中的 ReplicatedFirst 提供了封裝的功能,您可以呼叫您的客戶端指令發送網路訊息:
網路模組
-- 名為 NetworkManagerClient 的 ReplicatedFirst 中的模組腳本
local NetworkManagerClient = {}
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local remoteEvent = ReplicatedStorage:WaitForChild("RemoteEvent")
-- 封裝遠端對物件的 FireServer 功能
function NetworkManagerClient.FireServer(id, ...)
remoteEvent:FireServer(id, ...)
end
return NetworkManagerClient
Class.ServerScriptService 中的 ServerScriptService 使用 BindableEvents 為每個腳本連接到特定的 ID。當客戶端發送網路訊息時,與指定的 ID 相關的 1>Class.BindableEvent1> 會啟動。
-- 名為 NetworkManagerServer 的 ServerScript 服務中的模組腳本
local NetworkManagerServer = {}
local networkSignalList = {}
function NetworkManagerServer.GetServerEventSignal(id)
local bindableEvent = Instance.new("BindableEvent")
-- 將新的 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 並在收到邀請求時列出任何附加參數,以及在發出任何狀態時列出任何附加參數。
-- ServerScriptService 中的脚本
local ServerScriptService = game:GetService("ServerScriptService")
local NetworkManagerServer = require(ServerScriptService:WaitForChild("NetworkManagerServer"))
NetworkManagerServer.GetServerEventSignal("RequestA"):Connect(function(player, ...)
print("Received RequestA from", player, ...)
end)