Сеть: задержка, репликация и владение объектом
Понимать, что происходит между клиентом и сервером, и не перегружать сеть.
Теория
Между действием игрока и ответом сервера всегда проходит время — пинг. На нормальном соединении это десятки миллисекунд, на мобильном интернете бывает в разы больше. Игра, которая ждёт ответ на каждое движение, ощущается вязкой.
Поэтому клиент показывает результат сразу, а сервер подтверждает следом. Показ — это только показ: счёт, урон и предметы остаются за сервером. Если серверу нужно поправить клиента, он просто присылает верное состояние.
Физикой движущейся детали управляет одна из сторон — это и есть network ownership. Персонажем обычно владеет его клиент: так управление отзывчивое. Важными для игры объектами лучше владеть серверу, иначе их поведение зависит от чужой машины.
- Одно событие с таблицей лучше десяти событий подряд
- Не отправляй позицию каждый кадр — движок уже реплицирует персонажа сам
- SetNetworkOwner(nil) отдаёт деталь серверу
- Проверяй игру при плохом соединении: в Studio есть эмуляция задержки
Пример
Сервер копит изменения и отправляет их пачкой раз в полсекунды.
local ReplicatedStorage = game:GetService("ReplicatedStorage")local update = ReplicatedStorage:WaitForChild("ScoreUpdate")local pending = {}local function queue(player, score)pending[player.Name] = scoreendtask.spawn(function()while true dotask.wait(0.5)if next(pending) thenupdate:FireAllClients(pending)pending = {}endendend)return queue
Одна посылка с таблицей вместо потока мелких сообщений: канал разгружается.
Задача
Есть деталь-снаряд, которую сервер запускает в полёт. Отдай владение физикой серверу и объясни в комментарии, почему не клиенту.
- SetNetworkOwner работает только у незакреплённых деталей
- Владелец физики определяет, где она считается на самом деле
Показать решение
local projectile = Instance.new("Part")projectile.Size = Vector3.new(1, 1, 1)projectile.Position = Vector3.new(0, 10, 0)projectile.Anchored = falseprojectile.Parent = workspace-- Физику снаряда считает сервер: попадание влияет на счёт,-- а значит решение о нём не должно зависеть от машины игрока.projectile:SetNetworkOwner(nil)projectile.AssemblyLinearVelocity = Vector3.new(0, 0, -80)
Проверь себя
Что такое network ownership детали?
Показать ответ
Владелец физики считает движение объекта и рассылает результат остальным.
Как уменьшить нагрузку на сеть?
Показать ответ
Пачка изменений дешевле потока мелких сообщений, а логика остаётся на сервере.