Sử dụng lại mã

*Nội dung này được dịch bằng AI (Beta) và có thể có lỗi. Để xem trang này bằng tiếng Anh, hãy nhấp vào đây.

Sau khi tạo một vài kịch bản, không bao giờ lâu trước khi bạn muốn sử dụng lại một số mã giữa chúng.Tùy thuộc vào vị trí, ModuleScripts cho phép bạn tái sử dụng mã giữa các kịch bản trên các bên khác nhau của ranh giới khách-máy chủ hoặc cùng một bên của ranh giới.

Bạn có thể đặt các kịch bản module ở bất kỳ nơi nào bạn đặt kịch bản, nhưng ReplicatedStorage là một vị trí phổ biến; lưu trữ kịch bản module ở đây cho phép bạn tái sử dụng mã giữa máy chủ và khách hàng.

Cấu trúc của một kịch bản module

Trong Roblox Studio, thêm một kịch bản mô-đun vào ReplicatedStorage và đổi tên thành PickupManager. Mỗi ModuleScript bắt đầu với mã sau:


local module = {}
return module

Mã này tạo một bảng Luau trống và trả lại nó cho bất kỳ kịch bản nào yêu cầu kịch bản mô-đun.

Giá trị trả lại có thể là bất kỳ loại dữ liệu nào ngoại trừ nil, nhưng hầu hết các kịch bản module trả về một chức năng, một bảng hoặc một bảng các chức năng.Để tạo giá trị trả lại, các kịch bản module có thể chạy mã tùy ý, bao gồm việc yêu cầu các kịch bản module khác.

Ví dụ sau đây trả về một bảng với một chức năng duy nhất được gọi là getPickupBonus. Sao chép nó vào kịch bản module mới:


-- ModuleScript trong ReplicatedStorage
local PickupManager = {}
local defaultMultiplier = 1.25
local rarityMultipliers = {
common = 10,
uncommon = 20,
rare = 50,
legendary = 100
}
-- Thêm chức năng getPickupBonus vào bảng PickupManager
PickupManager.getPickupBonus = function(rarity)
local bonus = rarityMultipliers[rarity] * defaultMultiplier
return bonus
end
return PickupManager

Thêm chức năng vào một bảng không nhất thiết phải nghiêm ngặt - bạn chỉ có thể trả lại chính chức năng - nhưng đó là một mô hình tốt để theo dõi; nó cung cấp cho bạn một ngữ pháp dễ hiểu khi bạn gọi chức năng từ một kịch bản khác và cho phép bạn dễ dàng thêm nhiều chức năng vào kịch bản module theo thời gian.

Yêu cầu kịch bản module

Để tải một kịch bản mô-đun, bạn gọi chức năng require().Trong ReplicatedStorage , thêm một kịch bản mới, và thay đổi RunContext của nó thành Client .Sau đó, thêm mã sau để gọi chức năng PickupManager.getPickupBonus :

Tập lệnh khách trong ReplicatedStorage

local ReplicatedStorage = game:GetService("ReplicatedStorage")
-- Nhận giá trị được trả lại bởi ModuleScript
local PickupManager = require(ReplicatedStorage:WaitForChild("PickupManager"))
-- Gọi chức năng ModuleScript
local bonus = PickupManager.getPickupBonus("legendary")
print(bonus) --> 125

Lưu kịch bản mô-đun trong ReplicatedStorage cho phép bạn chia sẻ mã giữa máy chủ và khách hàng, để bạn có thể sử dụng cùng một mã để yêu cầu kịch bản từ ServerScriptService :

Tập lệnh trong ServerScriptService

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

Khi bạn gọi require() trên một ModuleScript, nó chạy một lần và trả về một mục duy nhất như một tham chiếu.Gọi lần nữa trả về cùng một tham chiếu chính xác, có nghĩa là nếu bạn sửa đổi một bảng trả về hoặc , các cuộc gọi tiếp theo sẽ trả lại tham chiếu đã sửa đổi đó.Chính mô-đun không chạy nhiều lần.

Nếu bạn cần một ModuleScript từ cả hai bên của ranh giới khách-máy chủ, như trong ví dụ trên, ModuleScript trả về một tham chiếu duy nhất cho mỗi bên.

Mẫu

Các kịch bản module có một số mẫu chung mà bạn có thể sử dụng để đơn giản hóa mã của bạn và tránh những sai lầm khi kinh nghiệm của bạn phát triển về kích thước và phức tạp.

Chia sẻ dữ liệu

Để liên kết dữ liệu với các đối tượng cụ thể, bạn có thể gán thuộc tính cho chúng hoặc tạo Configuration thư mục với các đối tượng giá trị như StringValue hoặc IntValue .Tuy nhiên, cả hai phương pháp đều gây rắc rối nếu bạn muốn thêm hoặc sửa hàng chục đối tượng hoặc giá trị dữ liệu.Họ cũng không lưu trữ bảng hoặc chức năng.

Nếu bạn muốn sửa đổi cùng một dữ liệu cho nhiều bản sao của cùng một đối tượng hoặc tái sử dụng cùng một dữ liệu cho các đối tượng khác nhau, lưu dữ liệu trong ModuleScripts .Nó là một cách dễ dàng hơn để bạn tái sử dụng dữ liệu trong các kịch bản khác, và bạn có thể lưu trữ các bảng và chức năng.

Ví dụ sau đây ModuleScript trong ReplicatedStorage lưu các giá trị cấu hình cho một khẩu súng chung:

ModuleScript trong ReplicatedStorage

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

Sự kiện tùy chỉnh

Các sự kiện tùy chỉnh cho phép các kịch bản giao tiếp với nhau, nhưng phải theo dõi các tham chiếu đến các đối tượng riêng lẻ BindableEvent có thể làm lộn xộn mã của bạn.

Bạn có thể sử dụng ModuleScripts để lưu BindableEvents và cung cấp các xử lý sự kiện tùy chỉnh được gắn trực tiếp vào các phương pháp của ModuleScript .

Các thẻ sau ModuleScript trong ReplicatedStorage có sự kiện tùy chỉnh bắt lửa khi công tắc thay đổi trạng thái:

ModuleScript trong ReplicatedStorage

local Switch = {}
-- Tạo binding để bất kỳ kịch bản nào có thể lắng nghe khi công tắc được thay đổi
local bindableEvent = Instance.new("BindableEvent")
Switch.Changed = bindableEvent.Event
local state = false
function Switch.flip()
state = not state
bindableEvent:Fire(state)
end
return Switch

Các kịch bản khách tiếp theo trong ReplicatedStorage kết nối một chức năng để gọi khi sự kiện Switch.Changed bắt lửa.

Tập lệnh trong ReplicatedStorage

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Switch = require(ReplicatedStorage:WaitForChild("Switch"))
Switch.Changed:Connect(function(newState)
print("Switch state is now", newState)
end
-- Thử lật một vài lần
task.wait(1)
Switch.flip()
task.wait(1)
Switch.flip()

Bọc lại

Việc bao gói là thực hành tạo một lớp trừu tượng xung quanh các đối tượng hoặc logic lập trình để che đi sự phức tạp.Bạn có thể sử dụng ModuleScripts để bao gói các đối tượng Roblox với chức năng Luau tùy chỉnh để đơn giản hóa mã.

Ví dụ, bạn có thể sử dụng bọc lại để:

  • Giản hóa giao tiếp giữa các mạng với một đối tượng duy nhất RemoteEvent.
  • Bọc mã xử lý lỗi xung quanh các dịch vụ nhạy cảm như DataStoreService .
  • Xác định các phương pháp tùy chỉnh để kiểm soát hoặc mở rộng các tính năng đối tượng Roblox.

Thật khó để theo dõi hàng chục đối tượng riêng lẻ RemoteEvent để triển khai mạng trong trò chơi của bạn.Bạn có thể sử dụng một ModuleScript để bao gói một RemoteEvent để giúp đơn giản hóa vấn đề này.Bằng cách bao gồm một tham số độc đáo id , bạn vẫn có thể gửi các tin nhắn mạng khác nhau trong khi chỉ sử dụng một RemoteEvent duy nhất.

Trong ví dụ dưới đây, ModuleScript có tên NetworkManagerClient bao gói phương pháp RemoteEvent:FireServer() để bao gồm thêm id đối số này.Ngoài ra, đoạn này ModuleScript tham chiếu đến đối tượng RemoteEvent bản thân nên bạn không cần phải tham chiếu nó trong các phần khác của mã.Bạn chỉ cần yêu cầu điều này ModuleScript để gửi tin nhắn mạng và không cần phải xử lý các đối tượng RemoteEvent trong phần còn lại của cơ sở mã nguồn của bạn.

Các chức năng bọc lại sau đây ModuleScript trong ReplicatedFirst cung cấp một chức năng bọc lại mà bạn có thể gọi vào các kịch bản khách để gửi một tin nhắn mạng:

Mạng Module

-- ModuleScript trong ReplicatedFirst có tên NetworkManagerClient
local NetworkManagerClient = {}
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local remoteEvent = ReplicatedStorage:WaitForChild("RemoteEvent")
-- Bao gói chức năng FireServer của đối tượng remote
function NetworkManagerClient.FireServer(id, ...)
remoteEvent:FireServer(id, ...)
end
return NetworkManagerClient

Các thẻ sau ModuleScript trong ServerScriptService sử dụng BindableEvents cho mỗi kịch bản kết nối với một ID cụ thể.Khi một khách hàng gửi một tin nhắn mạng, mỗi BindableEvent được liên kết với ID được định nghĩa bắt lửa.


-- ModuleScript trong ServerScriptService có tên NetworkManagerServer
local NetworkManagerServer = {}
local networkSignalList = {}
function NetworkManagerServer.GetServerEventSignal(id)
local bindableEvent = Instance.new("BindableEvent")
-- Kết nối BindableEvent mới với id
table.insert(networkSignalList, {
id = id,
bindableEvent = bindableEvent,
})
return bindableEvent.Event
end
-- Kết nối với
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local remoteEvent = ReplicatedStorage:WaitForChild("RemoteEvent")
remoteEvent.OnServerEvent:Connect(function(player, id, ...)
-- Tìm mọi sự kiện có thể gắn kết phù hợp với ID của sự kiện được nhận từ xa
for _, signal in networkSignalList do
if signal.id == id then
signal.bindableEvent:Fire(player, ...)
end
end
end)
return NetworkManagerServer

Các thông điệp sau LocalScript gửi một tin nhắn với ID RequestA với một tham số tùy chọn Hello.


-- Script địa phương trong ReplicatedFirst
local ReplicatedFirst = game:GetService("ReplicatedFirst")
local NetworkManagerClient = require(ReplicatedFirst:WaitForChild("NetworkManagerClient"))
NetworkManagerClient.FireServer("RequestA", "Hello")

Các kết nối sau Script kết nối với ID tin nhắn mạng RequestA và in ra một tuyên bố với bất kỳ tham số bổ sung nào khi nhận được yêu cầu.


-- Tập lệnh trong ServerScriptService
local ServerScriptService = game:GetService("ServerScriptService")
local NetworkManagerServer = require(ServerScriptService:WaitForChild("NetworkManagerServer"))
NetworkManagerServer.GetServerEventSignal("RequestA"):Connect(function(player, ...)
print("Received RequestA from", player, ...)
end)