Sự kiện từ xa và callback

*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.

Các trò chơi Roblox là đa người chơi theo mặc định, vì vậy tất cả các trò chơi tự động giao tiếp giữa máy chủ và các máy khách đã kết nối với người chơi. Trong trường hợp đơn giản nhất, khi người chơi di chuyển các nhân vật của mình, một số thuộc tính Humanoid, chẳng hạn như trạng thái, được truyền tới máy chủ, mà sau đó gửi thông tin này tới các máy khách kết nối khác.

Các sự kiện từ xa và callback cho phép bạn giao tiếp qua ranh giới máy khách-máy chủ:

  • RemoteEvents cho phép giao tiếp một chiều (gửi yêu cầu và không chờ phản hồi).
  • UnreliableRemoteEvents cho phép giao tiếp một chiều cho dữ liệu thay đổi liên tục hoặc không có tính quan trọng đối với trạng thái của trò chơi. Những sự kiện này đánh đổi thứ tự và độ tin cậy để cải thiện hiệu suất mạng.
  • RemoteFunctions cho phép giao tiếp hai chiều (gửi yêu cầu và chờ cho đến khi nhận được phản hồi từ người nhận).

Không giống như các sự kiện có thể gán, có tính hữu dụng hạn chế hơn, các trường hợp sử dụng cho các sự kiện và chức năng từ xa thì quá phong phú để liệt kê:

  • Gameplay - Gameplay cơ bản, chẳng hạn như một người chơi đạt đến cuối một cấp độ, có thể yêu cầu một sự kiện từ xa. Một tập lệnh máy khách thông báo cho máy chủ, và các tập lệnh máy chủ đặt lại vị trí của người chơi.
  • Xác minh máy chủ - Nếu một người chơi cố gắng uống một loại thuốc, liệu họ có thực sự loại thuốc đó không? Để đảm bảo sự công bằng, máy chủ phải là nguồn sự thật cho trò chơi. Một tập lệnh máy khách có thể sử dụng một sự kiện từ xa để thông báo cho máy chủ rằng người chơi đang uống loại thuốc, và sau đó các tập lệnh máy chủ có thể quyết định xem người chơi thực sự có loại thuốc đó hay không và có nên cấp bất kỳ lợi ích nào không.
  • Cập nhật giao diện người dùng - Khi trạng thái của trò chơi thay đổi, các tập lệnh máy chủ có thể sử dụng các sự kiện từ xa để thông báo cho các máy khách về những thay đổi điểm số, mục tiêu, v.v.
  • Mua bán trên Marketplace trong trò chơi - Để biết một ví dụ về triển khai sử dụng các chức năng từ xa, hãy xem Prompt subscription purchases.

Tham khảo nhanh

Các bảng sau đây phục vụ như một tham khảo nhanh cho cách sử dụng RemoteEventsRemoteFunctions để giao tiếp giữa máy khách và máy chủ.

Máy khách → Máy chủ
Máy kháchRemoteEvent:FireServer(args)
Máy chủRemoteEvent.OnServerEvent:Connect(function(player, args))
Máy chủ → Máy khách
Máy chủRemoteEvent:FireClient(player, args)
Máy kháchRemoteEvent.OnClientEvent:Connect(function(args))
Máy chủ → Tất cả máy khách
Máy chủRemoteEvent:FireAllClients(args)
Máy kháchRemoteEvent.OnClientEvent:Connect(function(args))

Sự kiện từ xa

Một đối tượng RemoteEvent tạo điều kiện cho việc giao tiếp không đồng bộ, một chiều qua ranh giới máy khách-máy chủ mà không cần chờ phản hồi.

Để tạo một RemoteEvent mới qua cửa sổ Explorer trong Studio:

  1. Di chuyển chuột qua container mà bạn muốn chèn RemoteEvent. Để đảm bảo cả máy chủ và máy khách có quyền truy cập, nó phải ở trong một vị trí mà cả hai bên có thể nhìn thấy, chẳng hạn như ReplicatedStorage, tuy nhiên trong một số trường hợp thì thích hợp hơn để lưu nó trong Workspace hoặc bên trong một Tool.
  2. Nhấp vào nút xuất hiện bên phải tên của container và chèn một thể hiện RemoteEvent.
  3. Đổi tên thể hiện để mô tả mục đích của nó.

Khi bạn đã tạo một RemoteEvent, nó có thể tạo điều kiện cho việc giao tiếp một chiều từ máy khách đến máy chủ, từ máy chủ đến máy khách, hoặc từ máy chủ đến tất cả máy khách.

Máy khách → Máy chủ
Máy chủ → Máy khách
Máy chủ → Tất cả Máy khách

Máy khách → máy chủ

Bạn có thể sử dụng một LocalScript để kích hoạt một sự kiện trên máy chủ bằng cách gọi phương thức FireServer() trên một RemoteEvent. Nếu bạn truyền các tham số cho FireServer(), chúng sẽ được chuyển đến bộ xử lý sự kiện trên máy chủ với một số giới hạn. Lưu ý rằng tham số đầu tiên của bộ xử lý sự kiện trên máy chủ luôn là đối tượng Player của máy khách gọi nó, và các tham số bổ sung theo sau.

Máy kháchRemoteEvent:FireServer(args)
Máy chủRemoteEvent.OnServerEvent:Connect(function(player, args))

Tập lệnh sau kết nối một bộ xử lý sự kiện với OnServerEvent mà tạo ra một Part mới trên máy chủ. Tập lệnh LocalScript kèm theo sau đó gọi FireServer() trên thể hiện RemoteEvent với màu và vị trí ColorPosition mong muốn cho phần này.

Kết nối sự kiện - Tập lệnh

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Workspace = game:GetService("Workspace")
-- Lấy tham chiếu đến thể hiện sự kiện từ xa
local remoteEvent = ReplicatedStorage:FindFirstChildOfClass("RemoteEvent")
local function onCreatePart(player, partColor, partPosition)
print(player.Name .. " đã kích hoạt RemoteEvent")
local newPart = Instance.new("Part")
newPart.Color = partColor
newPart.Position = partPosition
newPart.Parent = Workspace
end
-- Kết nối hàm với sự kiện
remoteEvent.OnServerEvent:Connect(onCreatePart)
Kích hoạt sự kiện - LocalScript

local ReplicatedStorage = game:GetService("ReplicatedStorage")
-- Lấy tham chiếu đến thể hiện sự kiện từ xa
local remoteEvent = ReplicatedStorage:FindFirstChildOfClass("RemoteEvent")
-- Kích hoạt sự kiện từ xa và truyền các tham số bổ sung
remoteEvent:FireServer(Color3.fromRGB(255, 0, 0), Vector3.new(0, 25, -20))

Máy chủ → máy khách

Bạn có thể sử dụng một Script để kích hoạt một sự kiện trên một máy khách bằng cách gọi phương thức FireClient() trên một RemoteEvent. Tham số đầu tiên cho FireClient() là đối tượng Player của máy khách mà bạn muốn phản hồi sự kiện, và các tham số bổ sung được truyền cho máy khách với một số giới hạn. Lưu ý rằng bộ xử lý sự kiện không cần bao gồm đối tượng Player là tham số đầu tiên của nó vì bạn có thể xác định người chơi trên máy khách với Players.LocalPlayer.

Máy chủRemoteEvent:FireClient(player, args)
Máy kháchRemoteEvent.OnClientEvent:Connect(function(args))

Tập lệnh LocalScript sau kết nối một bộ xử lý sự kiện với sự kiện OnClientEvent. Tập lệnh Script kèm theo sau đó lắng nghe các người chơi mới vào máy chủ và gọi FireClient() cho mỗi người với dữ liệu tùy ý.

Kết nối sự kiện - LocalScript

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Players = game:GetService("Players")
-- Lấy tham chiếu đến thể hiện sự kiện từ xa
local remoteEvent = ReplicatedStorage:FindFirstChildOfClass("RemoteEvent")
local player = Players.LocalPlayer
local function onNotifyPlayer(maxPlayers, respawnTime)
print("[Máy khách] Sự kiện nhận bởi người chơi", player.Name)
print(maxPlayers, respawnTime)
end
-- Kết nối hàm với sự kiện
remoteEvent.OnClientEvent:Connect(onNotifyPlayer)
Kích hoạt sự kiện - Tập lệnh

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Players = game:GetService("Players")
-- Lấy tham chiếu đến thể hiện sự kiện từ xa
local remoteEvent = ReplicatedStorage:FindFirstChildOfClass("RemoteEvent")
-- Lắng nghe các người chơi đến và phát sóng sự kiện từ xa cho mỗi người
local function onPlayerAdded(player)
print("[Máy chủ] Kích hoạt sự kiện cho người chơi", player.Name)
remoteEvent:FireClient(player, Players.MaxPlayers, Players.RespawnTime)
end
Players.PlayerAdded:Connect(onPlayerAdded)

Máy chủ → tất cả khách hàng

Bạn có thể sử dụng một Script để kích hoạt một sự kiện trên tất cả các máy khách bằng cách gọi phương thức FireAllClients() trên một RemoteEvent. Khác với FireClient(), phương thức FireAllClients() không yêu cầu một đối tượng Player vì nó phát sóng RemoteEvent đến tất cả máy khách.

Máy chủRemoteEvent:FireAllClients(args)
Máy kháchRemoteEvent.OnClientEvent:Connect(function(args))

Tập lệnh LocalScript sau kết nối một bộ xử lý sự kiện với sự kiện OnClientEvent mà xuất ra thời gian đếm ngược còn lại. Tập lệnh Script kèm theo sau đó gọi FireAllClients() trong một vòng lặp mỗi giây để phát sóng RemoteEvent cho tất cả các máy khách.

Kết nối sự kiện - LocalScript

local ReplicatedStorage = game:GetService("ReplicatedStorage")
-- Lấy tham chiếu đến thể hiện sự kiện từ xa
local remoteEvent = ReplicatedStorage:FindFirstChildOfClass("RemoteEvent")
local function onTimerUpdate(seconds)
print(seconds)
end
-- Kết nối hàm với sự kiện
remoteEvent.OnClientEvent:Connect(onTimerUpdate)
Kích hoạt sự kiện - Tập lệnh

local ReplicatedStorage = game:GetService("ReplicatedStorage")
-- Lấy tham chiếu đến thể hiện sự kiện từ xa
local remoteEvent = ReplicatedStorage:FindFirstChildOfClass("RemoteEvent")
local countdown = 5
-- Kích hoạt RemoteEvent mỗi giây cho đến khi hết thời gian
for timeRemaining = -1, countdown do
remoteEvent:FireAllClients(countdown - timeRemaining)
task.wait(1)
end

Callback từ xa

Một đối tượng RemoteFunction tạo điều kiện cho việc giao tiếp đồng bộ, hai chiều qua ranh giới máy khách-máy chủ. Người gửi một chức năng từ xa sẽ chờ cho đến khi nhận được phản hồi từ người nhận.

Để tạo một RemoteFunction mới qua cửa sổ Explorer trong Studio:

  1. Di chuyển chuột qua container mà bạn muốn chèn RemoteFunction. Để đảm bảo cả máy chủ và máy khách có quyền truy cập, nó phải ở trong một vị trí mà cả hai bên có thể nhìn thấy, chẳng hạn như ReplicatedStorage, tuy nhiên trong một số trường hợp thì thích hợp hơn để lưu nó trong Workspace hoặc bên trong một Tool.
  2. Nhấp vào nút xuất hiện bên phải tên của container và chèn một thể hiện RemoteFunction.
  3. Đổi tên thể hiện để mô tả mục đích của nó.

Khi bạn đã tạo một RemoteFunction, nó có thể tạo điều kiện cho việc giao tiếp hai chiều giữa máy khách và máy chủ hoặc giữa máy chủ và máy khách.

Máy khách → Máy chủ → Máy khách
Máy chủ → Máy khách → Máy chủ

Máy khách → máy chủ → máy khách

Bạn có thể sử dụng một LocalScript để gọi một hàm trên máy chủ bằng cách gọi phương thức InvokeServer() trên một RemoteFunction. Không giống như một sự kiện từ xa, LocalScript gọi RemoteFunction sẽ chờ cho đến khi callback trả về. Các tham số mà bạn truyền cho InvokeServer() sẽ được chuyển đến callback OnServerInvoke của RemoteFunction với một số giới hạn. Lưu ý rằng nếu bạn định nghĩa nhiều callback cho cùng một RemoteFunction, chỉ định nghĩa cuối cùng sẽ được thực thi.

Máy kháchRemoteFunction:InvokeServer(args)
Máy chủRemoteFunction.OnServerInvoke = function(player, args)

Tập lệnh Script sau định nghĩa hàm callback thông qua OnServerInvoke và trả về Part được yêu cầu qua giá trị return. Tập lệnh LocalScript kèm theo sau đó gọi InvokeServer() với các tham số bổ sung định nghĩa màu sắc và vị trí của phần được yêu cầu.

Kết nối callback - Tập lệnh

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Workspace = game:GetService("Workspace")
-- Lấy tham chiếu đến thể hiện chức năng từ xa
local remoteFunction = ReplicatedStorage:FindFirstChildOfClass("RemoteFunction")
-- Hàm callback
local function createPart(player, partColor, partPosition)
print(player.Name .. " đã yêu cầu một phần mới")
local newPart = Instance.new("Part")
newPart.Color = partColor
newPart.Position = partPosition
newPart.Parent = Workspace
return newPart
end
-- Đặt hàm làm callback của chức năng từ xa
remoteFunction.OnServerInvoke = createPart
Kích hoạt sự kiện - LocalScript

local ReplicatedStorage = game:GetService("ReplicatedStorage")
-- Lấy tham chiếu đến thể hiện chức năng từ xa
local remoteFunction = ReplicatedStorage:FindFirstChildOfClass("RemoteFunction")
-- Truyền một màu sắc và vị trí khi gọi callback
local newPart = remoteFunction:InvokeServer(Color3.fromRGB(255, 0, 0), Vector3.new(0, 25, -20))
-- Xuất ra tham chiếu đến phần đã trả về
print("Máy chủ đã tạo phần được yêu cầu:", newPart)

Máy chủ → máy khách → máy chủ

Bạn có thể sử dụng một Script để gọi một hàm trên máy khách bằng cách gọi phương thức InvokeClient() trên một RemoteFunction, nhưng nó có những rủi ro nghiêm trọng như sau:

  • Nếu máy khách gặp lỗi, máy chủ cũng gặp lỗi.
  • Nếu máy khách ngắt kết nối trong khi đang được gọi, InvokeClient() sẽ bị lỗi.
  • Nếu máy khách không trả về giá trị, máy chủ sẽ chờ mãi mãi.

Đối với các hành động mà không yêu cầu giao tiếp hai chiều, chẳng hạn như cập nhật giao diện người dùng, hãy sử dụng RemoteEvent và giao tiếp từ máy chủ đến máy khách.

Giới hạn tham số

Khi bạn kích hoạt một RemoteEvent hoặc gọi một RemoteFunction, nó sẽ chuyển tiếp bất kỳ tham số nào mà bạn truyền kèm với sự kiện hoặc đến hàm callback. Bất kỳ loại đối tượng Roblox nào chẳng hạn như Enum, Instance, hoặc các đối tượng khác đều có thể được truyền, cũng như các loại Luau như số, chuỗi, và boolean, tuy nhiên bạn nên cẩn thận khám phá các giới hạn sau.

Chỉ số không phải chuỗi

Nếu bất kỳ chỉ số nào của một bảng được truyền vào không phải là các loại chuỗi như một Instance, userdata, hoặc hàm, Roblox sẽ tự động chuyển đổi những chỉ số đó thành chuỗi.

Kết nối sự kiện - LocalScript

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local remoteEvent = ReplicatedStorage:FindFirstChildOfClass("RemoteEvent")
local function onEventFire(passedTable)
for k, v in passedTable do
print(typeof(k)) --> string
end
end
-- Kết nối hàm với sự kiện
remoteEvent.OnClientEvent:Connect(onEventFire)
Kích hoạt sự kiện - Tập lệnh

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Players = game:GetService("Players")
local Workspace = game:GetService("Workspace")
local remoteEvent = ReplicatedStorage:FindFirstChildOfClass("RemoteEvent")
-- Lắng nghe các người chơi đến và phát sóng sự kiện từ xa cho mỗi người
local function onPlayerAdded(player)
remoteEvent:FireClient(player,
{
[Workspace.Baseplate] = true
}
)
end
Players.PlayerAdded:Connect(onPlayerAdded)

Các hàm được truyền

Các hàm được bao gồm như các tham số cho một RemoteEvent hoặc RemoteFunction sẽ không được sao chép qua ranh giới máy khách-máy chủ, làm cho nó không thể truyền hàm từ xa. Thay vào đó, tham số nhận được ở phía bên nhận sẽ là nil.

Kết nối sự kiện - LocalScript

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local remoteEvent = ReplicatedStorage:FindFirstChildOfClass("RemoteEvent")
local function onClientEvent(func)
print(func) --> nil
end
remoteEvent.OnClientEvent:Connect(onClientEvent)
Kích hoạt sự kiện - Tập lệnh

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local remoteEvent = ReplicatedStorage:FindFirstChildOfClass("RemoteEvent")
local function testFunction()
print("Xin chào thế giới!")
end
-- Kích hoạt sự kiện từ xa với hàm như một tham số
remoteEvent:FireAllClients(testFunction)

Đánh chỉ số bảng

Nếu bạn truyền một bảng dữ liệu, đừng truyền một bảng hỗn hợp giữa các khóa số và khóa chuỗi. Thay vào đó, hãy truyền một bảng chỉ bao gồm hoàn toàn các cặp khóa-giá trị (từ điển) hoặc hoàn toàn các chỉ số số.

Kết nối sự kiện - Tập lệnh

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local remoteEvent = ReplicatedStorage:FindFirstChildOfClass("RemoteEvent")
local function onEventFire(player, passedTable)
for k, v in passedTable do
print(k .. " = " .. v)
--> 1 = Sword
--> 2 = Bow
--> CharName = Diva Dragonslayer
--> CharClass = Rogue
end
end
-- Kết nối hàm với sự kiện
remoteEvent.OnServerEvent:Connect(onEventFire)
Kích hoạt sự kiện - LocalScript

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local remoteEvent = ReplicatedStorage:FindFirstChildOfClass("RemoteEvent")
-- Bảng đánh chỉ số số
local inventoryData = {
"Sword", "Bow"
}
-- Bảng từ điển
local characterData = {
CharName = "Diva Dragonslayer",
CharClass = "Rogue"
}
remoteEvent:FireServer(inventoryData)
remoteEvent:FireServer(characterData)

Định danh bảng

Các bảng được truyền như các tham số cho các sự kiện/callback từ xa sẽ được sao chép, có nghĩa là chúng sẽ không hoàn toàn giống với những bảng được cung cấp khi kích hoạt sự kiện hoặc gọi callback. Các bảng được trả về cho người gọi cũng sẽ không hoàn toàn giống với những bảng được cung cấp. Bạn có thể chứng minh điều này bằng cách chạy tập lệnh sau trên một RemoteFunction và quan sát cách mà các định danh bảng khác nhau.

Kết nối callback - Tập lệnh

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local remoteFunction = ReplicatedStorage:FindFirstChildOfClass("RemoteFunction")
-- Hàm callback
local function returnTable(player, passedTable)
-- Xuất ra định danh bảng khi gọi
print(tostring(passedTable)) --> table: 0x48eb7aead27563d9
return passedTable
end
-- Đặt hàm làm callback của chức năng từ xa
remoteFunction.OnServerInvoke = returnTable
Kích hoạt sự kiện - LocalScript

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local remoteFunction = ReplicatedStorage:FindFirstChildOfClass("RemoteFunction")
local inventoryData = {
"Sword", "Bow"
}
-- Xuất ra định danh bảng gốc
print(tostring(inventoryData)) --> table: 0x059bcdbb2b576549
local invokeReturn = remoteFunction:InvokeServer(inventoryData)
-- Xuất ra định danh bảng khi trả về
print(tostring(invokeReturn)) --> table: 0x9fcae7919563a0e9

Metatables

Nếu một bảng có một metatable, tất cả thông tin metatable sẽ bị mất trong quá trình truyền. Trong mẫu mã sau, thuộc tính NumWheels là một phần của metatable của Car. Khi máy chủ nhận bảng sau, bảng truck có thuộc tính Name nhưng không có thuộc tính NumWheels.

Kết nối sự kiện - Tập lệnh

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local remoteEvent = ReplicatedStorage:FindFirstChildOfClass("RemoteEvent")
local function onEvent(player, param)
print(param) --> {["Name"] = "MyTruck"}
end
-- Kết nối hàm với sự kiện
remoteEvent.OnServerEvent:Connect(onEvent)
Kích hoạt sự kiện - LocalScript

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local remoteEvent = ReplicatedStorage:FindFirstChildOfClass("RemoteEvent")
local Car = {}
Car.NumWheels = 4
Car.__index = Car
local truck = {}
truck.Name = "MyTruck"
setmetatable(truck, Car)
-- Kích hoạt sự kiện với bảng bao gồm một metatable
remoteEvent:FireServer(truck)

Các thể hiện không được sao chép

Nếu một RemoteEvent hoặc RemoteFunction truyền một giá trị chỉ có thể nhìn thấy với người gửi, Roblox sẽ không sao chép nó qua ranh giới máy khách-máy chủ và truyền giá trị nil thay vào đó. Ví dụ, nếu một Script truyền một con cháu của ServerStorage, máy khách nghe sự kiện sẽ nhận được giá trị nil vì đối tượng đó không thể sao chép cho máy khách.

Kích hoạt sự kiện - Tập lệnh

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local ServerStorage = game:GetService("ServerStorage")
local Players = game:GetService("Players")
local remoteEvent = ReplicatedStorage:FindFirstChildOfClass("RemoteEvent")
-- Sẽ được nhận là "nil" vì máy khách không thể truy cập ServerStorage
local storedPart = Instance.new("Part")
storedPart.Parent = ServerStorage
local function onPlayerAdded(player)
remoteEvent:FireClient(player, storedPart)
end
Players.PlayerAdded:Connect(onPlayerAdded)

Tương tự, nếu bạn tạo một phần trong một LocalScript và cố gắng truyền cho một Script, máy chủ sẽ thấy nil vì phần này không thể sao chép cho máy chủ.

Kích hoạt sự kiện - LocalScript

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Workspace = game:GetService("Workspace")
local remoteEvent = ReplicatedStorage:FindFirstChildOfClass("RemoteEvent")
-- Sẽ được nhận là "nil" vì máy chủ không biết về phần này
local clientPart = Instance.new("Part")
clientPart.Parent = Workspace
remoteEvent:FireServer(clientPart)
©2026 Roblox Corporation. Roblox, logo Roblox và Powering Imagination là các nhãn hiệu đã đăng ký và chưa đăng ký của chúng tôi tại Hoa Kỳ và các quốc gia khác.