From 76fba9cb350b1480f37c52c0dff5b9c5d4678f6a Mon Sep 17 00:00:00 2001
From: min Команды для здоровья игрока: Пример 1 — шипы наносят урон: Пример 2 — аптечка лечит:
- Отдел Отдел В Lua для физики используется Пример — стрельба лучом из камеры игрока:
-
-
-
+
- game.player.hpтекущее здоровье (можно читать)
- game.player.damage(n)нанести урон
- game.player.heal(n)вылечить
- game.player.kill()мгновенно убить
- game.player.respawn()воскресить на спавне
-
- game.player.setSpawn(точка)новая точка возрождения
+ game.player.hpтекущее здоровье
+ game.player.damage(n)нанести урон
+ game.player.heal(n)вылечить
+ game.player.kill()мгновенно убить
+ game.player.respawn()воскресить на спавне
+
+ }
+ lua={game.player.setSpawn(точка)новая точка возрождения
+
+
}
+ />
+ humanoid.Healthтекущее здоровье
+ humanoid:TakeDamage(n)нанести урон
+ humanoid.Health = humanoid.Health + nвылечить
+ humanoid.Health = 0мгновенно убить
+ player:LoadCharacter()воскресить
+
+ player.RespawnLocation = spawnновая точка возрождения {`game.self.onTouch(() => {
+
+});`}}
+ lua={{`local part = script.Parent
+
+part.Touched:Connect(function(hit)
+ local humanoid = hit.Parent:FindFirstChild("Humanoid")
+ if humanoid then
+ humanoid:TakeDamage(20) -- отнять 20 здоровья
+ end
+end)`}}
+ />
{`game.self.onTouch(() => {
+
+});`}}
+ lua={{`local part = script.Parent
+
+part.Touched:Connect(function(hit)
+ local humanoid = hit.Parent:FindFirstChild("Humanoid")
+ if not humanoid then return end
+
+ -- добавить 50 здоровья, но не выше MaxHealth
+ humanoid.Health = math.min(humanoid.Health + 50, humanoid.MaxHealth)
+ print("+50 HP")
+ part:Destroy() -- аптечка исчезает
+end)`}}
+ />
>
),
},
@@ -2165,52 +2200,78 @@ TweenService:Create(door, TweenInfo.new(1), goal):Play()`}}
title: 'F2. Физика: raycast, импульсы, взрывы',
body: (
<>
- game.physics отвечает за «настоящую»
- физику:
-
-
+ raycast(откуда, куда, опции) — пустить
- невидимый луч и узнать, во что он попал. Так делают
- стрельбу;
- applyImpulse(ref, сила) — толкнуть объект
- (он должен быть не закреплён);
- explode(точка, радиус, опции) — взрыв.
- game.physics отвечает за «настоящую» физику:
+
+ >}
+ lua={<>
+ raycast(откуда, куда, опции) — луч для стрельбы;applyImpulse(ref, сила) — толкнуть объект;explode(точка, радиус, опции) — взрыв.workspace и стандартный Roblox API:
+
+ >}
+ />
workspace:Raycast(origin, dir, params) — луч;part:ApplyImpulse(Vector3) — толкнуть Part;Instance.new("Explosion") — создать взрыв.{`// При клике мышкой пускаем луч туда, куда смотрит игрок
-game.onClick(() => {
+
- hit.hit — попал ли луч во что-нибудь
- (да/нет). hit.ref — адрес объекта, в который
- попали.
- {`local UIS = game:GetService("UserInputService")
+local Players = game:GetService("Players")
+local player = Players.LocalPlayer
+local mouse = player:GetMouse()
+
+UIS.InputBegan:Connect(function(input)
+ if input.UserInputType ~= Enum.UserInputType.MouseButton1 then return end
+
+ local hrp = player.Character.HumanoidRootPart
+ local origin = hrp.Position + Vector3.new(0, 1.5, 0)
+ local direction = (mouse.Hit.Position - origin).Unit * 50
+
+ local raycastResult = workspace:Raycast(origin, direction)
+ if raycastResult then
+ print("Попал в объект:", raycastResult.Instance.Name)
+ end
+end)`}}
+ />
+ hit.hit — попал ли луч во что-нибудь.
+ hit.ref — адрес объекта.
+
+ raycastResult равно nil если
+ луч ни во что не попал. Иначе у него есть поля
+ .Instance (что попало),
+ .Position (точка попадания),
+ .Normal (нормаль поверхности).
+
@@ -2219,14 +2280,27 @@ game.onClick(() => { или сколько монет стоит товар.
{`// При старте игры запоминаем цену прямо на товаре
+ {`// При старте игры запоминаем цену прямо на товаре
game.scene.setData(game.self.ref, 'price', 50);
// Когда игрок кликает по товару — читаем цену
game.self.onClick(() => {
const price = game.scene.getData(game.self.ref, 'price');
game.ui.showText('Этот товар стоит ' + price + ' монет', 2);
-});`}
+});`}}
+ lua={{`local part = script.Parent
+
+-- При старте игры запоминаем цену прямо на товаре
+part:SetAttribute("Price", 50)
+
+-- Когда игрок кликает — читаем цену
+local clickDetector = Instance.new("ClickDetector", part)
+clickDetector.MouseClick:Connect(function(player)
+ local price = part:GetAttribute("Price")
+ print("Этот товар стоит " .. price .. " монет")
+end)`}}
+ />
Чем атрибут лучше обычной переменной? Переменная одна на весь скрипт. А атрибут — свой у каждого объекта. @@ -2242,36 +2316,61 @@ game.self.onClick(() => { body: ( <>
- Тег — это «ярлык», который можно повесить сразу - на много объектов. Потом одной командой можно найти их все. + Тег — это «ярлык» на объекте. Удобно ставить сразу на + много объектов и потом одной командой находить их все.
-tag(ref, 'звезда') | повесить тег |
untag(ref, 'звезда') | снять тег |
hasTag(ref, 'звезда') | есть ли тег |
getTagged('звезда') | все объекты с тегом |
game.scene.tag(ref, 'звезда')game.scene.untag(ref, 'звезда')game.scene.hasTag(ref, 'звезда')game.scene.getTagged('звезда')CollectionService:AddTag(part, "звезда") | повесить тег |
CollectionService:RemoveTag(part, "звезда") | снять тег |
CollectionService:HasTag(part, "звезда") | есть ли тег |
CollectionService:GetTagged("звезда") | все объекты с тегом |
Пример — игра «собери все звёзды»:
{`// Этот скрипт висит на звезде.
-// При старте помечаем звезду тегом.
+ {`// Этот скрипт висит на звезде.
game.scene.tag(game.self.ref, 'звезда');
-// Когда игрок коснулся — звезда собрана
game.self.onTouch(() => {
game.self.delete();
game.sound.play('coin');
- // сколько звёзд ещё осталось на сцене?
const left = game.scene.getTagged('звезда').length;
if (left === 0) {
game.ui.showText('Все звёзды собраны! Победа!', 3);
} else {
game.ui.showText('Осталось звёзд: ' + left, 1.5);
}
-});`}
+});`}}
+ lua={{`local CS = game:GetService("CollectionService")
+local part = script.Parent
+
+-- Помечаем звезду тегом
+CS:AddTag(part, "звезда")
+
+part.Touched:Connect(function()
+ part:Destroy()
+
+ local left = #CS:GetTagged("звезда")
+ if left == 0 then
+ print("Все звёзды собраны! Победа!")
+ else
+ print("Осталось звёзд: " .. left)
+ end
+end)`}}
+ />
Часто игра просит «подойди и нажми E»: открыть сундук,
- поговорить с торговцем, дёрнуть рычаг. Это делается
- командой game.self.onInteract:
+ поговорить с торговцем, дёрнуть рычаг.
{`game.self.onInteract(() => {
+ {`game.self.onInteract(() => {
game.ui.showText('Сундук открыт!', 2);
game.scene.spawnParticles('sparks',
game.self.position, { duration: 1 });
@@ -2298,11 +2397,26 @@ game.self.onTouch(() => {
}, {
text: 'Открыть сундук', // подсказка над объектом
distance: 4 // на сколько метров подойти
-});`}
+});`}}
+ lua={{`local part = script.Parent
+
+-- ProximityPrompt — стандартный Roblox-способ
+local prompt = Instance.new("ProximityPrompt")
+prompt.ActionText = "Открыть"
+prompt.ObjectText = "Сундук"
+prompt.MaxActivationDistance = 4
+prompt.KeyboardKeyCode = Enum.KeyCode.E
+prompt.Parent = part
+
+prompt.Triggered:Connect(function(player)
+ print("Сундук открыт!")
+ -- Можно создать эффект частиц или проиграть звук
+end)`}}
+ />
- Когда игрок подойдёт ближе чем на distance
- метров, над объектом появится подсказка с текстом.
- Нажатие E запустит функцию.
+ Когда игрок подойдёт на расстояние взаимодействия, над
+ объектом появится подсказка с текстом. Нажатие
+ E запустит функцию.
{`// Допустим, npc — это адрес созданного NPC.
-// Вешаем над ним табличку с именем.
+ {`// npc — это адрес созданного NPC.
game.scene.setLabel(npc.ref, 'Торговец Боб', {
color: '#ffffff',
height: 2.5 // на 2.5 метра над объектом
});
// Позже можно убрать табличку
-game.scene.clearLabel(npc.ref);`}
+game.scene.clearLabel(npc.ref);`}}
+ lua={{`-- BillboardGui в Roblox — это GUI поверх Part
+local part = workspace:WaitForChild("NPC")
+
+local billboard = Instance.new("BillboardGui")
+billboard.Size = UDim2.new(4, 0, 1, 0)
+billboard.StudsOffset = Vector3.new(0, 2.5, 0) -- над объектом
+billboard.Parent = part
+
+local label = Instance.new("TextLabel")
+label.BackgroundTransparency = 1
+label.Size = UDim2.new(1, 0, 1, 0)
+label.Text = "Торговец Боб"
+label.TextColor3 = Color3.new(1, 1, 1)
+label.TextScaled = true
+label.Parent = billboard
+
+-- Позже можно убрать табличку
+-- billboard:Destroy()`}}
+ />
>
),
},
{
id: 'pass-through',
- title: 'F7. Проходимость объектов (passThrough)',
+ title: 'F7. Проходимость объектов',
body: (
<>
Иногда стена должна стать проходимой — призрачная стена,
- секретный проход, исчезающий мост. Команда
- game.physics.passThrough(ref, true) делает
- объект «бесплотным»: видно его, но игрок проходит насквозь.
+ секретный проход, исчезающий мост.
{`// Когда игрок кликнет по стене — она пропустит сквозь себя
-game.self.onClick(() => {
+ {`game.self.onClick(() => {
game.physics.passThrough(game.self.ref, true);
game.scene.setOpacity(game.self.ref, 0.3); // полупрозрачная
game.ui.showText('Секретный проход открыт!', 2);
-});`}
+});`}}
+ lua={{`local part = script.Parent
+local clickDetector = Instance.new("ClickDetector", part)
+
+clickDetector.MouseClick:Connect(function(player)
+ part.CanCollide = false -- игрок проходит насквозь
+ part.Transparency = 0.7 -- полупрозрачная (0=видна, 1=невидима)
+ print("Секретный проход открыт!")
+end)`}}
+ />
Связи (constraints) соединяют объекты, чтобы они
- двигались вместе или по правилам физики. Отдел —
- game.constraints:
+ двигались вместе или по правилам физики.
Пример — качели на петле:
{`const swing = game.scene.findOne('Качели');
+ {`const swing = game.scene.findOne('Качели');
-// делаем качели на петле
const h = game.constraints.hinge(swing, {
- pivotX: 0, pivotZ: 0, // ось вращения
- angle: 30 // наклон на 30 градусов
+ pivotX: 0, pivotZ: 0,
+ angle: 30
});
// раскачиваем в другую сторону каждую секунду
let dir = -30;
game.every(1, () => {
h.setAngle(dir);
- dir = -dir; // меняем знак: 30 → -30 → 30 ...
-});`}
+ dir = -dir;
+});`}}
+ lua={{`-- В Roblox HingeConstraint — стандартный способ
+local swing = workspace:WaitForChild("Качели")
+local mount = workspace:WaitForChild("Опора") -- неподвижная точка
+
+-- Attachment'ы (точки крепления)
+local a0 = Instance.new("Attachment", mount)
+local a1 = Instance.new("Attachment", swing)
+
+local hinge = Instance.new("HingeConstraint")
+hinge.Attachment0 = a0
+hinge.Attachment1 = a1
+hinge.ActuatorType = Enum.ActuatorType.Servo
+hinge.ServoMaxTorque = 10000
+hinge.AngularSpeed = 2
+hinge.Parent = swing
+
+-- Раскачиваем
+local dir = 30
+while true do
+ hinge.TargetAngle = dir
+ task.wait(1)
+ dir = -dir
+end`}}
+ />
>
),
},