diff --git a/src/community/docsData.jsx b/src/community/docsData.jsx index c32689f..497c4a4 100644 --- a/src/community/docsData.jsx +++ b/src/community/docsData.jsx @@ -3835,15 +3835,13 @@ game.onTick(() => { }, { id: 'recipes-touch', - title: 'S2. Касание объекта (onTouch)', + title: 'S2. Касание объекта', body: ( <> -
- Самое частое событие — игрок коснулся объекта. Вешаем
- скрипт на объект и подписываемся через game.self.onTouch.
-
Самое частое событие — игрок коснулся объекта.
{`// Игрок наступил на объект — показать надпись и звук
+ {`// Игрок наступил на объект — показать надпись и звук
game.self.onTouch(() => {
game.ui.showText('Ты коснулся плиты!', 2);
game.sound.play('click');
@@ -3852,14 +3850,36 @@ game.self.onTouch(() => {
// Когда игрок ушёл с объекта
game.self.onUntouch(() => {
game.ui.showText('Отошёл', 1);
-});`}
- - Можно подписаться и на чужой объект из глобального - скрипта — найди его по имени: -
+});`}} + lua={{`local part = script.Parent
+
+-- Игрок наступил
+part.Touched:Connect(function(hit)
+ local player = game:GetService("Players"):GetPlayerFromCharacter(hit.Parent)
+ if player then
+ print("Ты коснулся плиты!")
+ end
+end)
+
+-- Игрок ушёл
+part.TouchEnded:Connect(function(hit)
+ local player = game:GetService("Players"):GetPlayerFromCharacter(hit.Parent)
+ if player then
+ print("Отошёл")
+ end
+end)`}}
+ />
+ Подписаться на чужой объект из глобального скрипта:
{`const trap = game.scene.findOne('Ловушка');
-trap.onTouch(() => game.player.damage(20));`}
+ {`local trap = workspace:WaitForChild("Ловушка")
+trap.Touched:Connect(function(hit)
+ local humanoid = hit.Parent:FindFirstChild("Humanoid")
+ if humanoid then humanoid:TakeDamage(20) end
+end)`}}
+ />
>
),
},
@@ -3870,30 +3890,65 @@ trap.onTouch(() => game.player.damage(20));`}
<>
Килблок — объект, который наносит урон или мгновенно - убивает, когда игрок его коснулся (лава, шипы, кислота). + убивает при касании (лава, шипы, кислота).
{`// Мгновенная смерть при касании
+ {`// Мгновенная смерть при касании
game.self.onTouch(() => {
game.player.kill();
- game.ui.showText('💀 Ты сгорел в лаве!', 2);
-});`}
+ game.ui.showText('Ты сгорел в лаве!', 2);
+});`}}
+ lua={{`local part = script.Parent
+
+part.Touched:Connect(function(hit)
+ local humanoid = hit.Parent:FindFirstChild("Humanoid")
+ if humanoid then
+ humanoid.Health = 0 -- мгновенная смерть
+ end
+end)`}}
+ />
Если хочешь не убивать сразу, а наносить урон:
-{`// Урон 25 при касании (учитывает кадры неуязвимости)
-game.self.onTouch(() => {
+ {`game.self.onTouch(() => {
game.player.damage(25);
- game.camera.shake(0.2, 0.3); // лёгкая тряска
-});`}
- - Постоянный урон, пока игрок стоит в зоне (например, - ядовитое облако) — урон каждые 0.5 сек, пока касается: -
-{`let inside = false;
+ game.camera.shake(0.2, 0.3);
+});`}}
+ lua={{`local part = script.Parent
+
+part.Touched:Connect(function(hit)
+ local humanoid = hit.Parent:FindFirstChild("Humanoid")
+ if humanoid then humanoid:TakeDamage(25) end
+end)`}}
+ />
+ Постоянный урон, пока игрок стоит в зоне:
+{`local part = script.Parent
+local inside = {} -- humanoid → true
+
+part.Touched:Connect(function(hit)
+ local h = hit.Parent:FindFirstChild("Humanoid")
+ if h then inside[h] = true end
+end)
+part.TouchEnded:Connect(function(hit)
+ local h = hit.Parent:FindFirstChild("Humanoid")
+ if h then inside[h] = nil end
+end)
+
+-- Урон каждые 0.5 сек пока стоит
+while true do
+ task.wait(0.5)
+ for h in pairs(inside) do
+ if h.Parent then h:TakeDamage(5) end
+ end
+end`}}
+ />
- Предмет исчезает, когда игрок его коснулся — основа - сбора монеток, ключей, бонусов. + Предмет исчезает при касании — основа сбора монет.
{`// Простое исчезновение + звук
-game.self.onTouch(() => {
+ {`game.self.onTouch(() => {
game.sound.play('coin');
game.self.delete();
-});`}
- - Со счётчиком: предмет сообщает глобальному скрипту, - тот считает. На монетке: -
-{`game.self.onTouch(() => {
- game.broadcast('coin'); // сообщить всем скриптам
+});`}}
+ lua={{`local part = script.Parent
+
+part.Touched:Connect(function(hit)
+ local h = hit.Parent:FindFirstChild("Humanoid")
+ if h then
+ part:Destroy()
+ end
+end)`}}
+ />
+ Со счётчиком: монетка увеличивает leaderstats игрока:
+В глобальном скрипте — приём и счёт:
+});`}} + lua={{`local part = script.Parent
+
+part.Touched:Connect(function(hit)
+ local player = game:GetService("Players"):GetPlayerFromCharacter(hit.Parent)
+ if not player then return end
+
+ -- Прибавить монетку в leaderstats
+ local stats = player:FindFirstChild("leaderstats")
+ if stats and stats:FindFirstChild("Монеты") then
+ stats.Монеты.Value = stats.Монеты.Value + 1
+ end
+
+ part:Destroy()
+end)`}}
+ />
+ JS: глобальный скрипт принимает broadcast и считает:
{`let score = 0;
+ {`let score = 0;
game.ui.score = 0;
game.onMessage('coin', () => {
score = score + 1;
- game.ui.score = score; // обновить счётчик в углу
- if (score >= 10) game.ui.showText('🏆 Собрал все!', 3);
-});`}
- game.broadcast.
- {`-- В Lua счёт уже в leaderstats игрока (см. код на монетке выше).
+-- Проверим достижение цели в глобальном скрипте:
+local Players = game:GetService("Players")
+
+Players.PlayerAdded:Connect(function(player)
+ -- Создаём leaderstats папку при заходе
+ local stats = Instance.new("Folder", player)
+ stats.Name = "leaderstats"
+ local coins = Instance.new("IntValue", stats)
+ coins.Name = "Монеты"
+ coins.Value = 0
+
+ coins.Changed:Connect(function(newVal)
+ if newVal >= 10 then
+ print("Собрал все!")
+ end
+ end)
+end)`}}
+ />
>
),
},
@@ -3949,34 +4039,62 @@ game.onMessage('coin', () => {
<>
При касании переместить игрока (портал) или - сдвинуть сам объект (движущаяся платформа). + сдвинуть сам объект.
-Портал — телепорт игрока в точку:
+Портал — телепорт игрока:
{`game.self.onTouch(() => {
- game.player.teleport(0, 20, 50); // x, y, z назначения
+ {`game.self.onTouch(() => {
+ game.player.teleport(0, 20, 50);
game.sound.play('win');
game.camera.shake(0.15, 0.2);
-});`}
-
- Сдвинуть сам объект при касании (например, опустить
- мост). game.self.move ставит новую позицию:
-
{`let opened = false;
+});`}}
+ lua={{`local part = script.Parent
+
+part.Touched:Connect(function(hit)
+ local h = hit.Parent:FindFirstChild("Humanoid")
+ if not h then return end
+ local hrp = hit.Parent:FindFirstChild("HumanoidRootPart")
+ if hrp then
+ hrp.CFrame = CFrame.new(0, 20, 50)
+ end
+end)`}}
+ />
+ Сдвинуть сам объект при касании (опустить мост):
+
- Плавно сдвинуть — через game.tween (анимация):
-
{`// дверь уезжает вбок за 1 секунду
-const p = game.self.position;
+ game.self.move(p.x, p.y - 3, p.z);
+});`}}
+ lua={{`local part = script.Parent
+local opened = false
+
+part.Touched:Connect(function(hit)
+ if opened then return end
+ if not hit.Parent:FindFirstChild("Humanoid") then return end
+ opened = true
+ part.Position = part.Position - Vector3.new(0, 3, 0)
+end)`}}
+ />
+ Плавно сдвинуть — через TweenService:
+{`local TweenService = game:GetService("TweenService")
+local part = script.Parent
+
+part.Touched:Connect(function(hit)
+ if not hit.Parent:FindFirstChild("Humanoid") then return end
+ local goal = { Position = part.Position + Vector3.new(4, 0, 0) }
+ TweenService:Create(part, TweenInfo.new(1), goal):Play()
+end)`}}
+ />
>
),
},
@@ -3986,88 +4104,169 @@ game.self.onTouch(() => {
body: (
<>
- Любой примитив можно создать и менять из - скрипта. Вот все свойства и как их задать. + Любой примитив можно создать и менять из скрипта.
Создать примитив со всеми свойствами:
-{`const box = game.scene.spawn('cube', {
- x: 0, y: 2, z: 0, // позиция
- sx: 2, sy: 1, sz: 3, // размер по осям (ширина/высота/глубина)
- rotationX: 0, rotationY: 0.8, rotationZ: 0, // поворот в радианах
- color: '#ff5533', // цвет (hex)
- material: 'neon', // matte | neon | metal | glass | studs
+ Создать примитив:
+ {`const box = game.scene.spawn('cube', {
+ x: 0, y: 2, z: 0,
+ sx: 2, sy: 1, sz: 3,
+ rotationX: 0, rotationY: 0.8, rotationZ: 0,
+ color: '#ff5533',
+ material: 'neon',
name: 'МойКуб',
- anchored: true, // true = висит на месте; false = падает (физика)
- canCollide: true, // false = игрок проходит насквозь
+ anchored: true,
+ canCollide: true,
visible: true,
- mass: 5, // масса (если anchored:false)
-});`}
- Типы примитивов для spawn:
{`'cube' 'sphere' 'cylinder' 'cone' 'pyramid' 'torus' 'wedge' 'cornerwedge' 'plane'`}
- Менять свойства уже существующего объекта:
-{`game.scene.setColor(box, '#00ff88'); // цвет
-game.scene.setMaterial(box, 'glass'); // материал
-game.scene.setVisible(box, false); // спрятать
-game.scene.setCollide(box, false); // сделать проходимым
-game.scene.setOpacity(box, 0.4); // полупрозрачность (1=видно, 0=невидимо)
-game.scene.setScale(box, 3, 1, 1); // новый размер
-game.scene.move(box, 5, 2, 0); // переместить
-game.scene.setRotation(box, 0, 1.57, 0); // повернуть (радианы)
-game.scene.setLabel(box, 'Привет!', { color:'#fff', height: 2.5 });`}
- - Удобнее — через объект-прокси (присваивание свойств): -
-{`const obj = game.scene.findOne('МойКуб');
+ mass: 5,
+});`}}
+ lua={{`local box = Instance.new("Part")
+box.Name = "МойКуб"
+box.Shape = Enum.PartType.Block
+box.Size = Vector3.new(2, 1, 3)
+box.Position = Vector3.new(0, 2, 0)
+box.Orientation = Vector3.new(0, math.deg(0.8), 0) -- градусы
+box.Color = Color3.fromRGB(255, 85, 51)
+box.Material = Enum.Material.Neon
+box.Anchored = true
+box.CanCollide = true
+box.Transparency = 0
+-- Если Anchored=false: box.Mass читается, не задаётся.
+-- Управляется через PhysicalProperties и Density.
+box.Parent = workspace`}}
+ />
+ Типы примитивов:
+{`Enum.PartType.Block / Ball / Cylinder / Wedge / CornerWedge
+-- Для cone/pyramid/torus используются MeshPart или SpecialMesh:
+local sphere = Instance.new("Part")
+sphere.Shape = Enum.PartType.Ball -- сфера`}}
+ />
+ Менять свойства существующего объекта:
+Math.PI/2 ≈ 1.57, 180° = Math.PI ≈ 3.14.
- {`-- Прямое присваивание свойств Part
+box.Color = Color3.fromRGB(0, 255, 136)
+box.Material = Enum.Material.Glass
+box.Transparency = 0.6 -- 0=видно, 1=невидимо
+box.CanCollide = false
+box.Size = Vector3.new(3, 1, 1)
+box.Position = Vector3.new(5, 2, 0)
+box.Orientation = Vector3.new(0, 90, 0)
+-- Скрыть: Transparency = 1 (или Parent = nil)
+
+box:Destroy() -- удалить`}}
+ />
+ Math.PI/2 ≈ 1.57.
+ }
+ lua={math.rad(90).
+
- Вращающийся объект (монета, портал) — крутим каждый
- кадр через game.onTick (dt = время кадра):
-
Вращающийся объект (монета, портал):
{`let angle = 0;
+ {`let angle = 0;
game.onTick((dt) => {
- angle = angle + dt * 2; // скорость вращения
+ angle = angle + dt * 2;
game.self.rotateY(angle);
-});`}
- Парение вверх-вниз (плавно качается):
-{`const start = game.self.position;
+});`}}
+ lua={{`local RunService = game:GetService("RunService")
+local part = script.Parent
+local angle = 0
+
+RunService.Heartbeat:Connect(function(dt)
+ angle = angle + dt * 2
+ part.CFrame = CFrame.new(part.Position) * CFrame.Angles(0, angle, 0)
+end)`}}
+ />
+ Парение вверх-вниз:
+Пульсация размера через tween (бесконечно туда-обратно):
-{`game.tween(game.self.ref, { sy: 1.4 }, {
+});`}}
+ lua={{`local RunService = game:GetService("RunService")
+local part = script.Parent
+local startPos = part.Position
+local t = 0
+
+RunService.Heartbeat:Connect(function(dt)
+ t = t + dt
+ local dy = math.sin(t * 2) * 0.4
+ part.Position = Vector3.new(startPos.X, startPos.Y + dy, startPos.Z)
+end)`}}
+ />
+ Пульсация размера:
+Мигание цветом каждые полсекунды:
-{`let on = false;
+});`}}
+ lua={{`local TweenService = game:GetService("TweenService")
+local part = script.Parent
+local origSize = part.Size
+
+local info = TweenInfo.new(
+ 0.6, Enum.EasingStyle.Quad, Enum.EasingDirection.InOut,
+ -1, -- бесконечно
+ true -- yoyo (туда-обратно)
+)
+local goal = { Size = Vector3.new(origSize.X, origSize.Y * 1.4, origSize.Z) }
+TweenService:Create(part, info, goal):Play()`}}
+ />
+ Мигание цветом:
+{`local part = script.Parent
+local on = false
+
+while true do
+ task.wait(0.5)
+ on = not on
+ part.Color = on and Color3.fromRGB(255, 0, 0)
+ or Color3.fromRGB(51, 0, 0)
+end`}}
+ />
>
),
},
@@ -4076,47 +4275,92 @@ game.every(0.5, () => {
title: 'S8. Кнопка по E и дверь',
body: (
<>
-
- Взаимодействие по клавише E (как в Roblox ProximityPrompt)
- — через game.self.onInteract. Появляется подсказка
- «[E] …» когда игрок рядом.
-
Взаимодействие по клавише E:
{`game.self.onInteract(() => {
+ {`game.self.onInteract(() => {
game.ui.showText('Открыто!', 2);
game.broadcast('open-door');
-}, { text: 'Открыть', key: 'e', distance: 4 });`}
- На двери — глобальный/объектный скрипт, который её открывает:
+}, { text: 'Открыть', key: 'e', distance: 4 });`}} + lua={{`local part = script.Parent
+
+local prompt = Instance.new("ProximityPrompt")
+prompt.ActionText = "Открыть"
+prompt.MaxActivationDistance = 4
+prompt.KeyboardKeyCode = Enum.KeyCode.E
+prompt.Parent = part
+
+-- BindableEvent для оповещения "open-door"
+local doorEvent = workspace:FindFirstChild("DoorOpenEvent")
+ or Instance.new("BindableEvent", workspace)
+doorEvent.Name = "DoorOpenEvent"
+
+prompt.Triggered:Connect(function(player)
+ print("Открыто!")
+ doorEvent:Fire()
+end)`}}
+ />
+ На двери:
{`const closed = game.self.position;
+ {`const closed = game.self.position;
game.onMessage('open-door', () => {
- // плавно уехать вверх (открыться)
- game.tween(game.self.ref, { y: closed.y + 4 }, { duration: 1, easing: 'ease' });
- game.self.setCollide(false); // через неё можно пройти
-});`}
+ game.tween(game.self.ref, { y: closed.y + 4 },
+ { duration: 1, easing: 'ease' });
+ game.self.setCollide(false);
+});`}}
+ lua={{`local TweenService = game:GetService("TweenService")
+local door = script.Parent
+local closedPos = door.Position
+
+local doorEvent = workspace:WaitForChild("DoorOpenEvent")
+
+doorEvent.Event:Connect(function()
+ local goal = { Position = closedPos + Vector3.new(0, 4, 0) }
+ TweenService:Create(door, TweenInfo.new(1), goal):Play()
+ door.CanCollide = false
+end)`}}
+ />
holdDuration: 1 в опциях onInteract — держать E
- 1 секунду (для важных действий). distance —
- с какого расстояния появляется подсказка.
+ holdDuration: 1 в onInteract / prompt.HoldDuration = 1
+ в Roblox — держать E одну секунду.
HUD-надписи в углу и по центру:
+HUD-надписи:
{`game.ui.score = 0; // счётчик «Очки: 0» в углу
-game.ui.score = 50; // обновить
-game.ui.timer = 60; // таймер mm:ss в углу
-game.ui.showText('Старт!', 2); // крупно по центру на 2 сек
-game.ui.set('hp', 'Жизни: 3', { x: 50, y: 90, color: '#fff' }); // своя метка
-game.ui.remove('hp'); // убрать метку`}
- Обратный отсчёт и проигрыш по времени:
-{`let time = 30;
+ {`game.ui.score = 0; // счётчик в углу
+game.ui.score = 50;
+game.ui.timer = 60; // таймер
+game.ui.showText('Старт!', 2);
+game.ui.set('hp', 'Жизни: 3', { x: 50, y: 90, color: '#fff' });
+game.ui.remove('hp');`} }
+ lua={{`-- В Roblox HUD = leaderstats папка (см. G7) или свой ScreenGui
+local Players = game:GetService("Players")
+local player = Players.LocalPlayer
+local gui = player:WaitForChild("PlayerGui")
+
+-- Своя метка по центру
+local screen = Instance.new("ScreenGui", gui)
+local label = Instance.new("TextLabel", screen)
+label.Size = UDim2.new(0.4, 0, 0.1, 0)
+label.Position = UDim2.new(0.3, 0, 0.4, 0)
+label.Text = "Старт!"
+label.TextScaled = true
+label.BackgroundTransparency = 0.5
+
+task.delay(2, function() screen:Destroy() end)`}}
+ />
+ Обратный отсчёт:
+Кнопка на экране (GUI) и обработка клика:
-{`const btn = game.gui.create('button', {
+});`}}
+ lua={{`local time = 30
+
+while time > 0 do
+ task.wait(1)
+ time = time - 1
+ print("Осталось: " .. time)
+end
+
+print("Время вышло!")
+-- Убить локального игрока
+local player = game:GetService("Players").LocalPlayer
+if player.Character and player.Character:FindFirstChild("Humanoid") then
+ player.Character.Humanoid.Health = 0
+end`}}
+ />
+ Кнопка GUI:
+{`local player = game:GetService("Players").LocalPlayer
+local gui = player:WaitForChild("PlayerGui")
+local screen = Instance.new("ScreenGui", gui)
+
+local btn = Instance.new("TextButton", screen)
+btn.Size = UDim2.new(0.2, 0, 0.08, 0)
+btn.Position = UDim2.new(0.4, 0, 0.8, 0)
+btn.Text = "НАЧАТЬ"
+btn.BackgroundColor3 = Color3.fromRGB(58, 110, 224)
+btn.TextColor3 = Color3.new(1, 1, 1)
+
+btn.MouseButton1Click:Connect(function()
+ print("Поехали!")
+ btn.Visible = false
+end)`}}
+ />
>
),
},
@@ -4144,34 +4420,75 @@ game.gui.onClick(btn, () => {
title: 'S10. Спавн, падение, проверка падения вниз',
body: (
<>
- Спавнить объекты с неба каждую секунду (ловилка):
+Спавнить объекты с неба каждую секунду:
{`game.every(1, () => {
+ {`game.every(1, () => {
const x = game.random(-10, 10);
game.scene.spawn('sphere', {
x: x, y: 20, z: 0,
color: '#ffd700', material: 'neon',
- anchored: false, // будет падать (физика)
- lifetime: 8 // само исчезнет через 8 сек
+ anchored: false,
+ lifetime: 8
});
-});`}
- - Игрок упал вниз (за карту) — вернуть на спавн. Проверяем - высоту каждый кадр: -
-{`game.onTick(() => {
+});`}}
+ lua={{`local Debris = game:GetService("Debris")
+
+while true do
+ task.wait(1)
+ local x = math.random(-10, 10)
+
+ local ball = Instance.new("Part")
+ ball.Shape = Enum.PartType.Ball
+ ball.Size = Vector3.new(1, 1, 1)
+ ball.Position = Vector3.new(x, 20, 0)
+ ball.Color = Color3.fromRGB(255, 215, 0)
+ ball.Material = Enum.Material.Neon
+ ball.Anchored = false -- падает
+ ball.Parent = workspace
+
+ Debris:AddItem(ball, 8) -- удалить через 8 сек
+end`}}
+ />
+ Игрок упал вниз:
+Финиш — дошёл до зоны, победа:
+});`}} + lua={{`local Players = game:GetService("Players")
+local RunService = game:GetService("RunService")
+
+RunService.Heartbeat:Connect(function()
+ local player = Players.LocalPlayer
+ if not player.Character then return end
+ local hrp = player.Character:FindFirstChild("HumanoidRootPart")
+ if hrp and hrp.Position.Y < -10 then
+ player:LoadCharacter() -- респавн
+ print("Упал!")
+ end
+end)`}}
+ />
+ Финиш:
{`game.self.onTouch(() => {
- game.ui.showText('🏁 ПОБЕДА!', 4);
+ {`game.self.onTouch(() => {
+ game.ui.showText('ПОБЕДА!', 4);
game.sound.play('win');
- game.player.setInputBlocked(true); // заморозить управление
-});`}
+ game.player.setInputBlocked(true);
+});`}}
+ lua={{`local part = script.Parent
+
+part.Touched:Connect(function(hit)
+ local h = hit.Parent:FindFirstChild("Humanoid")
+ if not h then return end
+ print("ПОБЕДА!")
+ h.WalkSpeed = 0 -- заморозить
+ h.JumpPower = 0
+end)`}}
+ />
>
),
},
@@ -4180,30 +4497,68 @@ game.gui.onClick(btn, () => {
title: 'S11. Враг, который идёт за игроком',
body: (
<>
- - NPC/враг, который преследует игрока и наносит урон. -
+NPC/враг, преследующий игрока:
{`const enemy = game.scene.spawnNpc('zombie', {
+ {`const enemy = game.scene.spawnNpc('zombie', {
x: 10, y: 0, z: 10,
hp: 100, name: 'Зомби', speed: 3
});
-enemy.follow('player'); // идти за игроком
+enemy.follow('player');
enemy.say('Хочу тебя поймать!', 3);
enemy.onDeath(() => {
game.ui.showText('Враг повержен!', 2);
- game.fx.damageFloater(enemy.position, 0, { isHeal: true });
-});`}
- Урон игроку, когда враг близко:
-{`game.every(0.5, () => {
+});
+
+// Урон когда близко
+game.every(0.5, () => {
const d = game.distance(enemy.position, game.player.position);
if (d < 2) game.player.damage(10);
-});`}
- game.fx.autoMobFloaters(true).
- {`-- Враг должен быть Model с Humanoid и HumanoidRootPart в workspace.
+-- Например workspace.Зомби.
+local Players = game:GetService("Players")
+local enemy = workspace:WaitForChild("Зомби")
+local humanoid = enemy:WaitForChild("Humanoid")
+local hrp = enemy:WaitForChild("HumanoidRootPart")
+
+-- Преследование игрока
+task.spawn(function()
+ while enemy.Parent and humanoid.Health > 0 do
+ local player = Players:GetPlayers()[1]
+ if player and player.Character then
+ local target = player.Character:FindFirstChild("HumanoidRootPart")
+ if target then
+ humanoid:MoveTo(target.Position)
+ end
+ end
+ task.wait(0.5)
+ end
+end)
+
+humanoid.Died:Connect(function()
+ print("Враг повержен!")
+end)
+
+-- Урон когда близко
+task.spawn(function()
+ while enemy.Parent and humanoid.Health > 0 do
+ task.wait(0.5)
+ local player = Players:GetPlayers()[1]
+ if player and player.Character then
+ local target = player.Character:FindFirstChild("HumanoidRootPart")
+ local playerHum = player.Character:FindFirstChild("Humanoid")
+ if target and playerHum then
+ local dist = (target.Position - hrp.Position).Magnitude
+ if dist < 2 then
+ playerHum:TakeDamage(10)
+ end
+ end
+ end
+ end
+end)`}}
+ />
>
),
},
@@ -4212,35 +4567,74 @@ enemy.onDeath(() => {
title: 'S12. Сохранение прогресса и лидерборд',
body: (
<>
- - Лидерборд (таблица очков справа) — объяви стат и - прибавляй: -
+Лидерборд:
{`game.leaderstats.define('Монеты', { initial: 0 });
-// прибавить текущему игроку:
-game.leaderstats.me.add('Монеты', 1);`}
- - Сохранение между сессиями (прогресс не теряется после - выхода): -
-{`// записать
-game.save.merge('progress', {
- patch: { level: 3 }, // обычные поля
- increment: { coins: 10 }, // атомарно прибавить
- max: { bestScore: 5000 } // запишется только если больше старого
+ {`game.leaderstats.define('Монеты', { initial: 0 });
+game.leaderstats.me.add('Монеты', 1);`} }
+ lua={{`-- leaderstats: см. G7
+local Players = game:GetService("Players")
+Players.PlayerAdded:Connect(function(player)
+ local stats = Instance.new("Folder", player)
+ stats.Name = "leaderstats"
+ local coins = Instance.new("IntValue", stats)
+ coins.Name = "Монеты"
+ coins.Value = 0
+end)
+
+-- Прибавить монетку (например, при сборе)
+local function addCoin(player, amount)
+ local stats = player:FindFirstChild("leaderstats")
+ if stats then
+ stats.Монеты.Value = stats.Монеты.Value + amount
+ end
+end`}}
+ />
+ Сохранение между сессиями:
+{`-- В Roblox сохранение через DataStoreService (требует онлайн-игру)
+local DataStoreService = game:GetService("DataStoreService")
+local progress = DataStoreService:GetDataStore("Progress")
+local Players = game:GetService("Players")
+
+Players.PlayerAdded:Connect(function(player)
+ -- Прочитать при входе
+ local success, data = pcall(function()
+ return progress:GetAsync(player.UserId)
+ end)
+ if success and data then
+ print("С возвращением! Уровень " .. (data.level or 1))
+ -- Применить прогресс: leaderstats.Монеты.Value = data.coins и т.п.
+ end
+end)
+
+Players.PlayerRemoving:Connect(function(player)
+ -- Сохранить при выходе
+ local data = {
+ level = 3,
+ coins = 10,
+ bestScore = 5000,
+ }
+ pcall(function()
+ progress:SetAsync(player.UserId, data)
+ end)
+end)`}}
+ />