Roblox · Pet Simulator · урок 1
Pet Simulator — симулятор, где игрок собирает питомцев, они бьют цели ради монет, монеты тратятся на яйца с новыми питомцами и на новые области. Сегодня: модель питомца и скрипт, который водит питомцев кругом за хозяином.
Синим — что добавляем на этом уроке.
ReplicatedStorage └─ Pets (Folder) — образцы питомцев ├─ Cat (Model) — PrimaryPart = Primary │ ├─ Primary (Part) — покрывает питомца: прозрачная, лицом вперёд │ ├─ Body, Head, Ear… (Part) — все Anchored, CanCollide и CanQuery выкл. │ ├─ Attack (ObjectValue) — кого атакует │ └─ Damage (NumberValue) — урон в секунду, например 10 └─ Bunny, Dog, … (Model) — так же Workspace └─ PlayerPets (Folder) — папки игроков с их питомцами ServerScriptService └─ MainScript (Script) StarterPlayer └─ StarterPlayerScripts └─ PetFollow (LocalScript)
Где: ServerScriptService · Script
Зачем: Папка игрока в PlayerPets и тестовый питомец.
-- все игроки
local Players = game:GetService("Players")
-- общее хранилище
local RS = game:GetService("ReplicatedStorage")
-- образцы питомцев
local pets = RS:WaitForChild("Pets")
-- питомцы игроков на карте
local playerPets = workspace:WaitForChild("PlayerPets")
-- питомец для проверки (до инвентаря)
local TEST_PET = "Cat"
-- игрок зашёл
Players.PlayerAdded:Connect(function(player)
-- папка для его питомцев
local folder = Instance.new("Folder")
-- имя = имя игрока
folder.Name = player.Name
-- в PlayerPets
folder.Parent = playerPets
-- тестовый питомец
local testPet = pets:FindFirstChild(TEST_PET)
-- сразу с игроком
if testPet then testPet:Clone().Parent = folder end
-- конец обработчика
end)
-- игрок вышел
Players.PlayerRemoving:Connect(function(player)
-- его папка
local folder = playerPets:FindFirstChild(player.Name)
-- убираем питомцев
if folder then folder:Destroy() end
-- конец обработчика
end)Где: StarterPlayer → StarterPlayerScripts · LocalScript
Зачем: Водит питомцев по кругу за хозяином.
-- события каждого кадра
local RunService = game:GetService("RunService")
-- все игроки
local Players = game:GetService("Players")
-- папки с питомцами игроков
local playerPets = workspace:WaitForChild("PlayerPets")
-- полный круг в радианах (360°)
local CIRCLE = math.pi * 2
-- точка на окружности вокруг персонажа
local function GetPosition(angle, radius)
-- x и z этой точки
return math.cos(angle) * radius, math.sin(angle) * radius
-- конец функции
end
-- двигает питомцев одного игрока
local function PositionPets(character, folder)
-- центр персонажа
local root = character:FindFirstChild("HumanoidRootPart")
-- его Humanoid
local humanoid = character:FindFirstChildOfClass("Humanoid")
-- персонаж ещё не загрузился
if not root or not humanoid then return end
-- питомцы игрока
local list = folder:GetChildren()
-- сколько их
local count = #list
-- чем больше питомцев, тем шире круг
local radius = 4 + count
-- размер персонажа
local _, characterSize = character:GetBoundingBox()
-- каждый питомец
for i, pet in ipairs(list) do
-- это модель с главной деталью
if pet:IsA("Model") and pet.PrimaryPart then
-- своё место на круге
local angle = i * (CIRCLE / count)
-- координаты места
local x, z = GetPosition(angle, radius)
-- размер питомца
local _, petSize = pet:GetBoundingBox()
-- питомец стоит на земле, а не висит
local offsetY = -characterSize.Y / 2 + petSize.Y / 2
-- подскоки: от 0 до 1
local bounce = math.sin(15 * time() + i) * 0.5 + 0.5
-- покачивание вбок
local tilt = math.cos(7 * time() + i) / 4
-- куда питомец хочет попасть
local goal
-- хозяин идёт
if humanoid.MoveDirection.Magnitude > 0 then
-- бежит рядом вприпрыжку
goal = root.CFrame * CFrame.new(x, offsetY + bounce, z) * CFrame.Angles(0, 0, tilt)
-- хозяин стоит
else
-- спокойно стоит рядом
goal = root.CFrame * CFrame.new(x, offsetY, z)
-- конец проверки
end
-- каждый кадр проходит 10% пути — плавно
pet:PivotTo(pet:GetPivot():Lerp(goal, 0.1))
-- конец проверки
end
-- конец перебора
end
-- конец функции
end
-- каждый кадр
RunService.RenderStepped:Connect(function()
-- папка каждого игрока
for _, folder in ipairs(playerPets:GetChildren()) do
-- игрок с таким именем
local player = Players:FindFirstChild(folder.Name)
-- он в игре и с персонажем
if player and player.Character then
-- двигаем его питомцев
PositionPets(player.Character, folder)
-- конец проверки
end
-- конец перебора
end
-- конец обработчика
end)Запусти Play (или Run) и убедись: