Урок 11 из 15

RemoteEvents: разговор клиента и сервера

Передавать события между сторонами и проверять то, что пришло от клиента.

Теория

Клиент и сервер — разные машины, и напрямую вызвать функцию друг у друга не могут. Между ними ставят RemoteEvent: объект-почтовый ящик, который лежит в ReplicatedStorage и виден обеим сторонам.

С клиента отправляют через FireServer, ловят на сервере через OnServerEvent. В обратную сторону — FireClient для одного игрока и FireAllClients для всех, ловят через OnClientEvent.

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

  • RemoteFunction ждёт ответ и может зависнуть — в сторону клиента её почти не используют
  • Не отправляй событие каждый кадр: сеть не бесплатная
  • Через Remote нельзя передать функцию и метатаблицу
  • Имя события должно говорить о действии: BuyItem, а не Event1

Пример

Клиент просит открыть дверь, сервер решает, можно ли.

ServerScriptService/OpenDoor.lua
  1. local ReplicatedStorage = game:GetService("ReplicatedStorage")
  2. local openDoor = ReplicatedStorage:WaitForChild("OpenDoor")
  3.  
  4. openDoor.OnServerEvent:Connect(function(player, doorName)
  5. if typeof(doorName) ~= "string" then
  6. return
  7. end
  8.  
  9. local door = workspace:FindFirstChild(doorName)
  10.  
  11. if not door or not door:IsA("BasePart") then
  12. return
  13. end
  14.  
  15. local character = player.Character
  16. local root = character and character:FindFirstChild("HumanoidRootPart")
  17.  
  18. if not root or (root.Position - door.Position).Magnitude > 12 then
  19. return
  20. end
  21.  
  22. door.CanCollide = false
  23. door.Transparency = 0.7
  24. end)

Сервер проверил тип, существование двери и расстояние. Клиент не может открыть дверь с другого конца карты.

Задача

Сделай RemoteEvent для смены цвета персонажа. Клиент отправляет название цвета, сервер принимает только три разрешённых значения и игнорирует остальные.

  • Список разрешённых цветов держи на сервере в таблице
  • Проверь тип аргумента до того, как искать его в таблице
Показать решение
ServerScriptService/Solution.lua
  1. local ReplicatedStorage = game:GetService("ReplicatedStorage")
  2. local setColor = ReplicatedStorage:WaitForChild("SetColor")
  3.  
  4. local ALLOWED = {
  5. red = Color3.fromRGB(200, 60, 60),
  6. green = Color3.fromRGB(60, 180, 90),
  7. blue = Color3.fromRGB(60, 110, 220),
  8. }
  9.  
  10. setColor.OnServerEvent:Connect(function(player, name)
  11. if typeof(name) ~= "string" then
  12. return
  13. end
  14.  
  15. local color = ALLOWED[name]
  16. local character = player.Character
  17.  
  18. if not color or not character then
  19. return
  20. end
  21.  
  22. for _, part in ipairs(character:GetChildren()) do
  23. if part:IsA("BasePart") then
  24. part.Color = color
  25. end
  26. end
  27. end)

Проверь себя

Какой аргумент OnServerEvent нельзя подделать?

Показать ответ

Игрока подставляет движок. Остальные аргументы пришли от клиента.

Где должен лежать RemoteEvent?

Показать ответ

ReplicatedStorage виден обеим сторонам — только там событие найдут оба.