Game Roblox adalah permainan multipemain secara default, sehingga semua permainan secara inheren berkomunikasi antara server dan klien yang terhubung dengan pemain. Dalam kasus yang paling sederhana, ketika pemain menggerakkan karakter mereka, properti tertentu dari Humanoid, seperti status, dikomunikasikan ke server, yang kemudian meneruskan informasi ini ke klien lain yang terhubung.
Peristiwa remote dan callback memungkinkan Anda untuk berkomunikasi melalui batasan klien-server:
- RemoteEvents memungkinkan komunikasi satu arah (mengirim permintaan dan tidak menunggu respons).
- UnreliableRemoteEvents memungkinkan komunikasi satu arah untuk data yang terus-menerus berubah atau tidak kritis terhadap status permainan. Peristiwa ini mengorbankan urutan dan keandalan demi meningkatkan kinerja jaringan.
- RemoteFunctions memungkinkan komunikasi dua arah (mengirim permintaan dan menunggu hingga respons diterima dari penerima).
Berbeda dengan peristiwa yang dapat diikat, yang memiliki utilitas yang lebih terbatas, kasus penggunaan untuk peristiwa remote dan fungsi terlalu banyak untuk dicantumkan:
- Gameplay - Gameplay dasar, seperti seorang pemain mencapai akhir level, dapat memerlukan peristiwa remote. Sebuah skrip klien memberi tahu server, dan skrip server mereset posisi pemain.
- Verifikasi server - Jika seorang pemain mencoba meminum ramuan, apakah mereka benar-benar memiliki ramuan itu? Untuk memastikan keadilan, server harus menjadi sumber kebenaran untuk sebuah permainan. Skrip klien dapat menggunakan peristiwa remote untuk memberi tahu server bahwa pemain sedang meminum ramuan, dan kemudian skrip server dapat memutuskan apakah pemain benar-benar memiliki ramuan tersebut dan apakah akan memberikan manfaat.
- Pembaruan antarmuka pengguna - Ketika status permainan berubah, skrip server dapat menggunakan peristiwa remote untuk memberi tahu klien tentang perubahan skor, tujuan, dll.
- Pembelian marketplace dalam permainan - Untuk implementasi contoh yang menggunakan fungsi remote, lihat Pembelian langganan prompt.
Referensi Cepat
Tabel berikut berfungsi sebagai referensi cepat untuk cara menggunakan RemoteEvents dan RemoteFunctions untuk berkomunikasi antara klien dan server.
| Klien → Server | |
|---|---|
| Klien | RemoteEvent:FireServer(args) |
| Server | RemoteEvent.OnServerEvent:Connect(function(player, args)) |
| Server → Klien | |
| Server | RemoteEvent:FireClient(player, args) |
| Klien | RemoteEvent.OnClientEvent:Connect(function(args)) |
| Server → Semua Klien | |
| Server | RemoteEvent:FireAllClients(args) |
| Klien | RemoteEvent.OnClientEvent:Connect(function(args)) |
Peristiwa Remote
Objek RemoteEvent memfasilitasi komunikasi asinkron, satu arah di antara batasan klien-server tanpa menunggu respons.
Untuk membuat RemoteEvent baru melalui jendela Explorer di Studio:
- Arahkan kursor ke wadah tempat Anda ingin memasukkan RemoteEvent. Untuk memastikan akses baik dari server maupun klien, ia harus berada di tempat di mana kedua sisi dapat melihatnya, seperti di ReplicatedStorage, meskipun dalam beberapa kasus adalah hal yang tepat untuk menyimpannya di Workspace atau di dalam Tool.
- Klik tombol ⊕ yang muncul di sebelah kanan nama wadah dan masukkan instance RemoteEvent.
- Ubah nama instance untuk menjelaskan tujuannya.
Setelah Anda membuat RemoteEvent, ia dapat memfasilitasi komunikasi satu arah dari klien ke server, dari server ke klien, atau dari server ke semua klien.



Klien → server
Anda dapat menggunakan LocalScript untuk memicu peristiwa di server dengan memanggil metode FireServer() pada RemoteEvent. Jika Anda meneruskan argumen ke FireServer(), argumen tersebut diteruskan ke pengendali peristiwa di server dengan batasan tertentu batasan argumen. Perhatikan bahwa parameter pertama dari pengendali peristiwa di server selalu merupakan objek Player dari klien yang memanggilnya, dan parameter tambahan mengikuti.
| Klien | RemoteEvent:FireServer(args) |
| Server | RemoteEvent.OnServerEvent:Connect(function(player, args)) |
Script Script berikut menghubungkan pengendali peristiwa ke OnServerEvent yang membuat Part baru di server. LocalScript yang menyertainya kemudian memanggil FireServer() pada instance RemoteEvent dengan Color dan Position yang diinginkan untuk bagian tersebut.
Koneksi Peristiwa - Script
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Workspace = game:GetService("Workspace")
-- Dapatkan referensi ke instance peristiwa remote
local remoteEvent = ReplicatedStorage:FindFirstChildOfClass("RemoteEvent")
local function onCreatePart(player, partColor, partPosition)
print(player.Name .. " memicu RemoteEvent")
local newPart = Instance.new("Part")
newPart.Color = partColor
newPart.Position = partPosition
newPart.Parent = Workspace
end
-- Hubungkan fungsi ke peristiwa
remoteEvent.OnServerEvent:Connect(onCreatePart)
Pemicu Peristiwa - LocalScriptlocal ReplicatedStorage = game:GetService("ReplicatedStorage")-- Dapatkan referensi ke instance peristiwa remotelocal remoteEvent = ReplicatedStorage:FindFirstChildOfClass("RemoteEvent")-- Memicu peristiwa remote dan meneruskan argumen tambahanremoteEvent:FireServer(Color3.fromRGB(255, 0, 0), Vector3.new(0, 25, -20))
Server → klien
Anda dapat menggunakan Script untuk memicu peristiwa di klien dengan memanggil metode FireClient() pada RemoteEvent. Argumen pertama untuk FireClient() adalah objek Player dari klien yang ingin Anda tanggapi peristiwa tersebut, dan argumen tambahan diteruskan ke klien dengan batasan tertentu batasan argumen. Perhatikan bahwa pengendali peristiwa tidak perlu menyertakan objek Player sebagai argumen pertamanya karena Anda dapat menentukan pemain di klien dengan Players.LocalPlayer.
| Server | RemoteEvent:FireClient(player, args) |
| Klien | RemoteEvent.OnClientEvent:Connect(function(args)) |
Script LocalScript berikut menghubungkan pengendali peristiwa ke peristiwa OnClientEvent. Skrip Script yang menyertainya kemudian mendengarkan pemain yang masuk ke server dan memanggil FireClient() untuk setiap pemain dengan data acak.
Koneksi Peristiwa - LocalScript
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Players = game:GetService("Players")
-- Dapatkan referensi ke instance peristiwa remote
local remoteEvent = ReplicatedStorage:FindFirstChildOfClass("RemoteEvent")
local player = Players.LocalPlayer
local function onNotifyPlayer(maxPlayers, respawnTime)
print("[Klien] Peristiwa diterima oleh pemain", player.Name)
print(maxPlayers, respawnTime)
end
-- Hubungkan fungsi ke peristiwa
remoteEvent.OnClientEvent:Connect(onNotifyPlayer)
Pemicu Peristiwa - Script
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Players = game:GetService("Players")
-- Dapatkan referensi ke instance peristiwa remote
local remoteEvent = ReplicatedStorage:FindFirstChildOfClass("RemoteEvent")
-- Dengarkan pemain yang masuk dan kirim peristiwa remote ke masing-masing
local function onPlayerAdded(player)
print("[Server] Memicu peristiwa untuk pemain", player.Name)
remoteEvent:FireClient(player, Players.MaxPlayers, Players.RespawnTime)
end
Players.PlayerAdded:Connect(onPlayerAdded)
Server → semua klien
Anda dapat menggunakan Script untuk memicu peristiwa di semua klien dengan memanggil metode FireAllClients() pada RemoteEvent. Berbeda dengan FireClient(), metode FireAllClients() tidak memerlukan objek Player karena itu memicu RemoteEvent ke semua klien.
| Server | RemoteEvent:FireAllClients(args) |
| Klien | RemoteEvent.OnClientEvent:Connect(function(args)) |
Script LocalScript berikut menghubungkan pengendali peristiwa ke peristiwa OnClientEvent yang menampilkan waktu hitung mundur yang tersisa. Skrip Script yang menyertainya kemudian memanggil FireAllClients() dalam loop setiap detik untuk memicu RemoteEvent untuk semua klien.
Koneksi Peristiwa - LocalScript
local ReplicatedStorage = game:GetService("ReplicatedStorage")
-- Dapatkan referensi ke instance peristiwa remote
local remoteEvent = ReplicatedStorage:FindFirstChildOfClass("RemoteEvent")
local function onTimerUpdate(seconds)
print(seconds)
end
-- Hubungkan fungsi ke peristiwa
remoteEvent.OnClientEvent:Connect(onTimerUpdate)
Pemicu Peristiwa - Scriptlocal ReplicatedStorage = game:GetService("ReplicatedStorage")-- Dapatkan referensi ke instance peristiwa remotelocal remoteEvent = ReplicatedStorage:FindFirstChildOfClass("RemoteEvent")local countdown = 5-- Memicu RemoteEvent setiap detik hingga waktu habisfor timeRemaining = -1, countdown doremoteEvent:FireAllClients(countdown - timeRemaining)task.wait(1)end
Callback Remote
Objek RemoteFunction memfasilitasi komunikasi sinkron, dua arah di antara batasan klien-server. Pengirim fungsi remote akan menunggu hingga menerima respons dari penerima.
Untuk membuat RemoteFunction baru melalui jendela Explorer di Studio:
- Arahkan kursor ke wadah tempat Anda ingin memasukkan RemoteFunction. Untuk memastikan akses baik dari server maupun klien, ia harus berada di tempat di mana kedua sisi dapat melihatnya, seperti di ReplicatedStorage, meskipun dalam beberapa kasus adalah hal yang tepat untuk menyimpannya di Workspace atau di dalam Tool.
- Klik tombol ⊕ yang muncul di sebelah kanan nama wadah dan masukkan instance RemoteFunction.
- Ubah nama instance untuk menjelaskan tujuannya.
Setelah Anda membuat RemoteFunction, ia dapat memfasilitasi komunikasi dua arah antara klien dan server atau antara server dan klien.


Klien → server → klien
Anda dapat menggunakan LocalScript untuk memanggil fungsi di server dengan memanggil metode InvokeServer() pada RemoteFunction. Berbeda dengan peristiwa remote, LocalScript yang memanggil RemoteFunction menunggu hingga callback mengembalikan hasil. Argumen yang Anda teruskan ke InvokeServer() diteruskan ke callback OnServerInvoke dari RemoteFunction dengan batasan tertentu batasan argumen. Perhatikan bahwa jika Anda mendefinisikan beberapa callback untuk RemoteFunction yang sama, hanya definisi terakhir yang akan dieksekusi.
| Klien | RemoteFunction:InvokeServer(args) |
| Server | RemoteFunction.OnServerInvoke = function(player, args) |
Script Script berikut mendefinisikan fungsi callback melalui OnServerInvoke dan mengembalikan Part yang diminta melalui nilai return-nya. Skrip LocalScript yang menyertainya kemudian memanggil InvokeServer() dengan argumen tambahan yang mendefinisikan warna dan posisi bagian yang diminta.
Koneksi Callback - Script
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Workspace = game:GetService("Workspace")
-- Dapatkan referensi ke instance fungsi remote
local remoteFunction = ReplicatedStorage:FindFirstChildOfClass("RemoteFunction")
-- Fungsi callback
local function createPart(player, partColor, partPosition)
print(player.Name .. " meminta sebuah bagian baru")
local newPart = Instance.new("Part")
newPart.Color = partColor
newPart.Position = partPosition
newPart.Parent = Workspace
return newPart
end
-- Atur fungsi sebagai callback untuk fungsi remote
remoteFunction.OnServerInvoke = createPart
Pemanggilan Peristiwa - LocalScriptlocal ReplicatedStorage = game:GetService("ReplicatedStorage")-- Dapatkan referensi ke instance fungsi remotelocal remoteFunction = ReplicatedStorage:FindFirstChildOfClass("RemoteFunction")-- Meneruskan warna dan posisi saat memanggil callbacklocal newPart = remoteFunction:InvokeServer(Color3.fromRGB(255, 0, 0), Vector3.new(0, 25, -20))-- Output referensi bagian yang dikembalikanprint("Server membuat bagian yang diminta:", newPart)
Server → klien → server
Anda dapat menggunakan Script untuk memanggil fungsi di klien dengan memanggil metode InvokeClient() pada RemoteFunction, tetapi ini memiliki risiko serius sebagai berikut:
- Jika klien mengeluarkan kesalahan, server juga akan menghasilkan kesalahan.
- Jika klien terputus saat dipanggil, InvokeClient() mengeluarkan kesalahan.
- Jika klien tidak mengembalikan nilai, server akan menunggu selamanya.
Untuk aksi yang tidak memerlukan komunikasi dua arah, seperti memperbarui antarmuka pengguna, gunakan RemoteEvent dan berkomunikasi dari server ke klien.
Batasan Argumen
Ketika Anda memicu RemoteEvent atau memanggil RemoteFunction, ia meneruskan argumen apa pun yang Anda teruskan dengan peristiwa atau fungsi callback. Jenis objek Roblox apa pun seperti Enum, Instance, atau lainnya dapat diteruskan, serta tipe-tipe Luau seperti angka, string, dan boolean, meskipun Anda harus mencermati batasan berikut.
Indeks non-string
Jika ada indeks dari tabel yang diteruskan adalah tipe non-string seperti Instance, userdata, atau fungsi, Roblox secara otomatis mengkonversi indeks tersebut menjadi string.
Koneksi Peristiwa - 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
-- Hubungkan fungsi ke peristiwa
remoteEvent.OnClientEvent:Connect(onEventFire)
Pemicu Peristiwa - Script
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Players = game:GetService("Players")
local Workspace = game:GetService("Workspace")
local remoteEvent = ReplicatedStorage:FindFirstChildOfClass("RemoteEvent")
-- Dengarkan pemain yang masuk dan kirim peristiwa remote ke masing-masing
local function onPlayerAdded(player)
remoteEvent:FireClient(player,
{
[Workspace.Baseplate] = true
}
)
end
Players.PlayerAdded:Connect(onPlayerAdded)
Fungsi yang diteruskan
Fungsi yang disertakan sebagai argumen untuk RemoteEvent atau RemoteFunction tidak akan direplikasi melintasi batasan klien-server, sehingga tidak mungkin untuk meneruskan fungsi secara remote. Sebaliknya, argumen yang dihasilkan di sisi penerima akan menjadi nil.
Koneksi Peristiwa - LocalScript
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local remoteEvent = ReplicatedStorage:FindFirstChildOfClass("RemoteEvent")
local function onClientEvent(func)
print(func) --> nil
end
remoteEvent.OnClientEvent:Connect(onClientEvent)
Pemicu Peristiwa - Script
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local remoteEvent = ReplicatedStorage:FindFirstChildOfClass("RemoteEvent")
local function testFunction()
print("Hallo dunia!")
end
-- Memicu peristiwa remote dengan fungsi sebagai argumen
remoteEvent:FireAllClients(testFunction)
Indeks Tabel
Jika Anda meneruskan tabel data, jangan meneruskan tabel campuran dari kunci numerik dan string. Sebagai gantinya, kirimkan tabel yang terdiri sepenuhnya dari pasangan kunci-nilai (kamus) atau sepenuhnya dari indeks numerik.
Koneksi Peristiwa - Script
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 = Pedang
--> 2 = Busur
--> CharName = Diva Dragonslayer
--> CharClass = Rogue
end
end
-- Hubungkan fungsi ke peristiwa
remoteEvent.OnServerEvent:Connect(onEventFire)
Pemicu Peristiwa - LocalScriptlocal ReplicatedStorage = game:GetService("ReplicatedStorage")local remoteEvent = ReplicatedStorage:FindFirstChildOfClass("RemoteEvent")-- Tabel yang diindeks secara numeriklocal inventoryData = {"Pedang", "Busur"}-- Tabel kamuslocal characterData = {CharName = "Diva Dragonslayer",CharClass = "Rogue"}remoteEvent:FireServer(inventoryData)remoteEvent:FireServer(characterData)
Identitas Tabel
Tabel yang diteruskan sebagai argumen untuk peristiwa remote/callback disalin, artinya mereka tidak akan identik persis dengan yang diberikan saat memicu peristiwa atau memanggil callback. Tabel yang dikembalikan kepada pemanggil juga tidak akan identik persis dengan yang diberikan. Anda dapat menunjukkan hal ini dengan menjalankan skrip berikut pada RemoteFunction dan mengamati bagaimana identitas tabel berbeda.
Koneksi Callback - Script
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local remoteFunction = ReplicatedStorage:FindFirstChildOfClass("RemoteFunction")
-- Fungsi callback
local function returnTable(player, passedTable)
-- Output identitas tabel saat pemanggilan
print(tostring(passedTable)) --> table: 0x48eb7aead27563d9
return passedTable
end
-- Atur fungsi sebagai callback untuk fungsi remote
remoteFunction.OnServerInvoke = returnTable
Pemanggilan Peristiwa - LocalScriptlocal ReplicatedStorage = game:GetService("ReplicatedStorage")local remoteFunction = ReplicatedStorage:FindFirstChildOfClass("RemoteFunction")local inventoryData = {"Pedang", "Busur"}-- Output identitas tabel asliprint(tostring(inventoryData)) --> table: 0x059bcdbb2b576549local invokeReturn = remoteFunction:InvokeServer(inventoryData)-- Output identitas tabel saat kembaliprint(tostring(invokeReturn)) --> table: 0x9fcae7919563a0e9
Metatables
Jika sebuah tabel memiliki metatable, semua informasi metatable hilang dalam transfer. Dalam contoh kode berikut, properti NumWheels adalah bagian dari metatable Car. Ketika server menerima tabel berikut, tabel truck memiliki properti Name tetapi tidak memiliki properti NumWheels.
Koneksi Peristiwa - Script
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local remoteEvent = ReplicatedStorage:FindFirstChildOfClass("RemoteEvent")
local function onEvent(player, param)
print(param) --> {["Name"] = "MyTruck"}
end
-- Hubungkan fungsi ke peristiwa
remoteEvent.OnServerEvent:Connect(onEvent)
Pemicu Peristiwa - LocalScriptlocal ReplicatedStorage = game:GetService("ReplicatedStorage")local remoteEvent = ReplicatedStorage:FindFirstChildOfClass("RemoteEvent")local Car = {}Car.NumWheels = 4Car.__index = Carlocal truck = {}truck.Name = "MyTruck"setmetatable(truck, Car)-- Memicu peristiwa dengan tabel yang menyertakan metatableremoteEvent:FireServer(truck)
Instance yang tidak direplikasi
Jika sebuah RemoteEvent atau RemoteFunction meneruskan nilai yang hanya terlihat oleh pengirim, Roblox tidak mereplikasinya melintasi batasan klien-server dan meneruskan nil sebagai ganti nilai tersebut. Sebagai contoh, jika sebuah Script meneruskan keturunan dari ServerStorage, maka klien yang mendengarkan peristiwa tersebut akan menerima nilai nil karena objek tersebut tidak dapat direplikasi untuk klien.
Pemicu Peristiwa - Script
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local ServerStorage = game:GetService("ServerStorage")
local Players = game:GetService("Players")
local remoteEvent = ReplicatedStorage:FindFirstChildOfClass("RemoteEvent")
-- Akan diterima sebagai "nil" karena klien tidak dapat mengakses ServerStorage
local storedPart = Instance.new("Part")
storedPart.Parent = ServerStorage
local function onPlayerAdded(player)
remoteEvent:FireClient(player, storedPart)
end
Players.PlayerAdded:Connect(onPlayerAdded)
Demikian pula, jika Anda membuat sebuah bagian dalam LocalScript dan mencoba meneruskannya ke Script, server akan melihat nil karena bagian tersebut tidak dapat direplikasi untuk server.
Pemicu Peristiwa - LocalScriptlocal ReplicatedStorage = game:GetService("ReplicatedStorage")local Workspace = game:GetService("Workspace")local remoteEvent = ReplicatedStorage:FindFirstChildOfClass("RemoteEvent")-- Akan diterima sebagai "nil" karena server tidak mengetahui bagian inilocal clientPart = Instance.new("Part")clientPart.Parent = WorkspaceremoteEvent:FireServer(clientPart)