Мультиплеер: сервер, клиент и репликация

Любая игра в Roblox — сетевая. Даже если ты играешь один, рядом работает сервер, и всё, что должно быть общим, происходит на нём.

Что реплицируется, а что нет

  • Изменения сервера в Workspace видят все игроки
  • Изменения клиента у себя в Workspace видит только он сам
  • Содержимое ReplicatedStorage доступно обеим сторонам
  • ServerStorage и ServerScriptService клиенту не видны вовсе

RemoteEvent и RemoteFunction

Чтобы клиент и сервер поговорили, между ними ставят RemoteEvent — сообщение без ответа — или RemoteFunction, когда ответ нужен. Лежат они в ReplicatedStorage.

RemoteFunction, вызванная сервером у клиента, может не вернуться никогда: клиент вправе зависнуть или выйти. Поэтому в сторону клиента почти всегда используют RemoteEvent.

ServerScriptService/ClaimReward.lua
  1. local ReplicatedStorage = game:GetService("ReplicatedStorage")
  2. local claim = ReplicatedStorage:WaitForChild("ClaimReward")
  3.  
  4. local lastClaim = {}
  5.  
  6. claim.OnServerEvent:Connect(function(player)
  7. local now = os.clock()
  8.  
  9. if lastClaim[player.UserId] and now - lastClaim[player.UserId] < 60 then
  10. return
  11. end
  12.  
  13. lastClaim[player.UserId] = now
  14. local coins = player:WaitForChild("leaderstats"):WaitForChild("Coins")
  15. coins.Value += 10
  16. end)

Первый аргумент OnServerEvent — сам игрок, и подделать его нельзя. Всё остальное — данные от клиента, их проверяют.

Ping и предсказание

Между нажатием у игрока и ответом сервера проходит время. Если ждать ответ на каждое действие, игра будет ощущаться вязкой.

Поэтому клиент показывает результат сразу, а сервер подтверждает его следом. Важно, что показ — это только показ: очки, предметы и урон остаются за сервером.