Roblox · Pet Simulator · урок 3
Яйцо за монеты: подходишь, жмёшь E — на экране яйцо качается, лопается, и появляется выпавший питомец с редкостью. Кто выпадет — решают шансы в таблице.
Синим — что добавляем на этом уроке.
Workspace └─ Eggs (Folder) └─ Start Egg (Part / MeshPart) — яйцо, Anchored └─ ProximityPrompt (ProximityPrompt) ReplicatedStorage └─ Events (Folder) └─ HatchEggEvent (RemoteEvent) ServerScriptService ├─ MainScript → PlayerInfo (Folder) │ └─ Pets (Folder) — купленные питомцы (StringValue) └─ EggsServer (Script) └─ EggInfo (ModuleScript) StarterGui └─ EggSystemGui (ScreenGui) — Enabled выкл., ResetOnSpawn выкл. └─ EggViewport (ViewportFrame) — AnchorPoint 0.5, 0.5, Position 0.5, 0, 0.5, 0 └─ EggName, EggRarity (TextLabel) — Visible выкл. StarterPlayer → StarterPlayerScripts └─ EggsLocal (LocalScript)
Где: ServerScriptService → EggsServer · ModuleScript
Зачем: Цены яиц и шансы питомцев.
-- все яйца
local eggData = {
-- имя — как у яйца в папке Eggs
["Start Egg"] = {
-- цена
EggPrice = 10,
-- валюта: Coins или Gems
EggMoney = "Coins",
-- кто может выпасть
EggPets = {
-- имя — как у модели в Pets; Chance — вес
{PetName = "Bunny", Chance = 50, Rarity = "Common"},
-- ещё один
{PetName = "Cat", Chance = 50, Rarity = "Common"},
-- конец списка
},
-- конец яйца
},
-- яйцо за кристаллы
["Gem Egg"] = {
-- цена
EggPrice = 5,
-- валюта
EggMoney = "Gems",
-- кто может выпасть
EggPets = {
-- чаще
{PetName = "Dog", Chance = 70, Rarity = "Uncommon"},
-- реже
{PetName = "Dragon", Chance = 30, Rarity = "Rare"},
-- конец списка
},
-- конец яйца
},
-- конец таблицы
}
-- отдаём таблицу
return eggDataГде: ServerScriptService · Script
Зачем: Покупка яйца и случайный питомец.
-- данные яиц
local eggData = require(script.EggInfo)
-- общее хранилище
local RS = game:GetService("ReplicatedStorage")
-- яйца на карте
local eggsFolder = workspace:WaitForChild("Eggs")
-- показать анимацию игроку
local hatchEggEvent = RS:WaitForChild("Events"):WaitForChild("HatchEggEvent")
-- кто сейчас открывает яйцо
local hatching = {}
-- случайный питомец с учётом шансов
local function SelectRandomPet(petTable)
-- сумма шансов
local total = 0
-- складываем — не обязательно 100
for _, info in ipairs(petTable) do total += info.Chance end
-- случайное число
local roll = math.random(1, total)
-- накопленный шанс
local sum = 0
-- по питомцам
for _, info in ipairs(petTable) do
-- прибавляем
sum += info.Chance
-- число попало на этого питомца
if roll <= sum then return info end
-- конец перебора
end
-- конец функции
end
-- каждое яйцо
for _, egg in ipairs(eggsFolder:GetChildren()) do
-- его данные
local info = eggData[egg.Name]
-- надпись «Купить»
local prompt = egg:FindFirstChildWhichIsA("ProximityPrompt", true)
-- чего-то нет
if not info or not prompt then
-- подсказка в Output
warn("Яйцо " .. egg.Name .. ": нет данных в EggInfo или ProximityPrompt")
-- всё есть
else
-- название
prompt.ObjectText = egg.Name
-- цена на надписи
prompt.ActionText = info.EggPrice .. " " .. info.EggMoney
-- игрок нажал E
prompt.Triggered:Connect(function(player)
-- уже открывает — ждём
if hatching[player] then return end
-- нужная валюта
local money = player.leaderstats:FindFirstChild(info.EggMoney)
-- не хватает
if not money or money.Value < info.EggPrice then return end
-- открывает
hatching[player] = true
-- списываем
money.Value -= info.EggPrice
-- кто выпал
local selected = SelectRandomPet(info.EggPets)
-- запись о питомце
local petValue = Instance.new("StringValue")
-- имя
petValue.Name = selected.PetName
-- в папку Pets игрока
petValue.Parent = player.Pets
-- анимация у игрока
hatchEggEvent:FireClient(player, egg.Name, selected.PetName, selected.Rarity)
-- пока идёт анимация
task.wait(5)
-- можно открыть следующее
hatching[player] = nil
-- конец обработчика
end)
-- конец проверки
end
-- конец перебора
endГде: StarterPlayer → StarterPlayerScripts · LocalScript
Зачем: Анимация открытия яйца.
-- общее хранилище
local RS = game:GetService("ReplicatedStorage")
-- анимации
local TS = game:GetService("TweenService")
-- яйца
local eggsFolder = workspace:WaitForChild("Eggs")
-- образцы питомцев
local pets = RS:WaitForChild("Pets")
-- сигнал от сервера
local hatchEggEvent = RS:WaitForChild("Events"):WaitForChild("HatchEggEvent")
-- этот игрок
local player = game.Players.LocalPlayer
-- его интерфейс
local playerGui = player:WaitForChild("PlayerGui")
-- окно яйца
local eggSystemGui = playerGui:WaitForChild("EggSystemGui")
-- 3D-окошко
local eggViewport = eggSystemGui:WaitForChild("EggViewport")
-- имя питомца
local eggName = eggViewport:WaitForChild("EggName")
-- редкость
local eggRarity = eggViewport:WaitForChild("EggRarity")
-- размер окна
local FULL = UDim2.fromScale(0.3, 0.5)
-- окно схлопнуто
local HIDDEN = UDim2.fromScale(0, 0)
-- убрать из окошка яйцо, питомца и камеру
local function Clear()
-- всё внутри
for _, obj in ipairs(eggViewport:GetChildren()) do
-- камеры, детали, модели (надписи остаются)
if obj:IsA("Camera") or obj:IsA("PVInstance") then obj:Destroy() end
-- конец перебора
end
-- конец функции
end
-- поставить объект в окошко
local function Show(object)
-- старое убираем
Clear()
-- новый объект
object.Parent = eggViewport
-- его размер
local size = object:IsA("Model") and object:GetExtentsSize() or object.Size
-- камера окошка
local camera = Instance.new("Camera")
-- отходим тем дальше, чем больше объект
camera.CFrame = CFrame.new(0, 0, size.Magnitude * 1.1)
-- в окошко
camera.Parent = eggViewport
-- окошко смотрит через неё
eggViewport.CurrentCamera = camera
-- конец функции
end
-- плавно меняет размер окна
local function Resize(size)
-- за полсекунды
local tween = TS:Create(eggViewport, TweenInfo.new(0.5), {Size = size})
-- запускаем
tween:Play()
-- ждём
tween.Completed:Wait()
-- конец функции
end
-- наклон окна — яйцо качается
local function Rotate(rotation)
-- за 0,3 с
local tween = TS:Create(eggViewport, TweenInfo.new(0.3, Enum.EasingStyle.Sine), {Rotation = rotation})
-- запускаем
tween:Play()
-- ждём
tween.Completed:Wait()
-- конец функции
end
-- вся анимация открытия
local function HatchEgg(eggNameText, petName, petRarity)
-- интерфейсы, которые прячем
local hidden = {}
-- весь интерфейс игрока
for _, ui in ipairs(playerGui:GetChildren()) do
-- включённый и не окно яйца
if ui:IsA("ScreenGui") and ui ~= eggSystemGui and ui.Enabled then
-- прячем
ui.Enabled = false
-- запоминаем, чтобы вернуть только их
table.insert(hidden, ui)
-- конец проверки
end
-- конец перебора
end
-- надписи пока скрыты
eggName.Visible = false
-- тоже
eggRarity.Visible = false
-- окно схлопнуто
eggViewport.Size = HIDDEN
-- включаем окно яйца
eggSystemGui.Enabled = true
-- копия яйца
local egg = eggsFolder:FindFirstChild(eggNameText):Clone()
-- в центр окошка
egg:PivotTo(CFrame.new())
-- показываем
Show(egg)
-- окно раскрывается
Resize(FULL)
-- два раза
for _ = 1, 2 do
-- качнулось вправо
Rotate(20)
-- влево
Rotate(-20)
-- конец цикла
end
-- ровно
Rotate(0)
-- окно схлопнулось — яйцо «лопнуло»
Resize(HIDDEN)
-- образец питомца
local template = pets:FindFirstChild(petName)
-- есть
if template then
-- копия
local petModel = template:Clone()
-- мордой к камере
petModel:PivotTo(CFrame.Angles(0, math.rad(180), 0))
-- показываем
Show(petModel)
-- конец проверки
end
-- имя
eggName.Text = petName
-- редкость
eggRarity.Text = petRarity
-- показываем
eggName.Visible = true
-- показываем
eggRarity.Visible = true
-- окно раскрывается
Resize(FULL)
-- любуемся
task.wait(3)
-- схлопываем
Resize(HIDDEN)
-- чистим
Clear()
-- выключаем окно
eggSystemGui.Enabled = false
-- возвращаем спрятанные интерфейсы
for _, ui in ipairs(hidden) do ui.Enabled = true end
-- конец функции
end
-- сервер прислал питомца — анимация
hatchEggEvent.OnClientEvent:Connect(HatchEgg)Запусти Play (или Run) и убедись: