RemoteEvents: разговор клиента и сервера
Передавать события между сторонами и проверять то, что пришло от клиента.
Теория
Клиент и сервер — разные машины, и напрямую вызвать функцию друг у друга не могут. Между ними ставят RemoteEvent: объект-почтовый ящик, который лежит в ReplicatedStorage и виден обеим сторонам.
С клиента отправляют через FireServer, ловят на сервере через OnServerEvent. В обратную сторону — FireClient для одного игрока и FireAllClients для всех, ловят через OnClientEvent.
Первым аргументом OnServerEvent всегда приходит сам игрок, и его подделать нельзя — это единственное, чему сервер верит без проверки. Всё остальное прислал клиент, а значит проверять нужно и тип, и диапазон, и право на действие.
- RemoteFunction ждёт ответ и может зависнуть — в сторону клиента её почти не используют
- Не отправляй событие каждый кадр: сеть не бесплатная
- Через Remote нельзя передать функцию и метатаблицу
- Имя события должно говорить о действии: BuyItem, а не Event1
Пример
Клиент просит открыть дверь, сервер решает, можно ли.
local ReplicatedStorage = game:GetService("ReplicatedStorage")local openDoor = ReplicatedStorage:WaitForChild("OpenDoor")openDoor.OnServerEvent:Connect(function(player, doorName)if typeof(doorName) ~= "string" thenreturnendlocal door = workspace:FindFirstChild(doorName)if not door or not door:IsA("BasePart") thenreturnendlocal character = player.Characterlocal root = character and character:FindFirstChild("HumanoidRootPart")if not root or (root.Position - door.Position).Magnitude > 12 thenreturnenddoor.CanCollide = falsedoor.Transparency = 0.7end)
Сервер проверил тип, существование двери и расстояние. Клиент не может открыть дверь с другого конца карты.
Задача
Сделай RemoteEvent для смены цвета персонажа. Клиент отправляет название цвета, сервер принимает только три разрешённых значения и игнорирует остальные.
- Список разрешённых цветов держи на сервере в таблице
- Проверь тип аргумента до того, как искать его в таблице
Показать решение
local ReplicatedStorage = game:GetService("ReplicatedStorage")local setColor = ReplicatedStorage:WaitForChild("SetColor")local ALLOWED = {red = Color3.fromRGB(200, 60, 60),green = Color3.fromRGB(60, 180, 90),blue = Color3.fromRGB(60, 110, 220),}setColor.OnServerEvent:Connect(function(player, name)if typeof(name) ~= "string" thenreturnendlocal color = ALLOWED[name]local character = player.Characterif not color or not character thenreturnendfor _, part in ipairs(character:GetChildren()) doif part:IsA("BasePart") thenpart.Color = colorendendend)
Проверь себя
Какой аргумент OnServerEvent нельзя подделать?
Показать ответ
Игрока подставляет движок. Остальные аргументы пришли от клиента.
Где должен лежать RemoteEvent?
Показать ответ
ReplicatedStorage виден обеим сторонам — только там событие найдут оба.