Roblox · Движение
Предмет-крюк: кликаешь по стене, крыше или дереву — к точке тянется верёвка, и персонаж летит туда. Дальность 120 studs.
Синим — что нужно создать.
StarterPack └─ Grapple (Tool) ├─ Handle (Part) — крюк; CanCollide выкл. └─ GrappleLocal (LocalScript)
Где: StarterPack → Grapple · LocalScript
Зачем: Луч, верёвка и полёт к точке.
-- крюк-кошка (Tool)
local tool = script.Parent
-- события каждого кадра
local RunService = game:GetService("RunService")
-- этот игрок
local player = game.Players.LocalPlayer
-- мышь — куда целимся
local mouse = player:GetMouse()
-- дальность крюка
local RANGE = 120
-- скорость притягивания
local PULL_SPEED = 80
-- уже летим
local busy = false
-- клик (тап) с крюком в руках
tool.Activated:Connect(function()
-- уже летим
if busy then return end
-- персонаж
local character = player.Character
-- Humanoid
local humanoid = character and character:FindFirstChildOfClass("Humanoid")
-- центр
local root = character and character:FindFirstChild("HumanoidRootPart")
-- нет персонажа
if not humanoid or not root or humanoid.Health <= 0 then return end
-- настройки луча
local params = RaycastParams.new()
-- не замечать список
params.FilterType = Enum.RaycastFilterType.Exclude
-- свой персонаж
params.FilterDescendantsInstances = {character}
-- луч из камеры через курсор
local result = workspace:Raycast(mouse.UnitRay.Origin, mouse.UnitRay.Direction * 1000, params)
-- никуда не попал или слишком далеко
if not result or (result.Position - root.Position).Magnitude > RANGE then return end
-- летим
busy = true
-- точка зацепа
local hook = Instance.new("Part")
-- не падает
hook.Anchored = true
-- не мешает
hook.CanCollide = false
-- не ловит лучи
hook.CanQuery = false
-- невидимая
hook.Transparency = 1
-- маленькая
hook.Size = Vector3.new(0.2, 0.2, 0.2)
-- где зацепились
hook.Position = result.Position
-- в мир (только у этого игрока)
hook.Parent = workspace
-- начало верёвки
local a0 = Instance.new("Attachment")
-- в крюке в руке
a0.Parent = tool.Handle
-- конец верёвки
local a1 = Instance.new("Attachment")
-- в точке зацепа
a1.Parent = hook
-- верёвка — линия между точками
local rope = Instance.new("Beam")
-- от руки
rope.Attachment0 = a0
-- до зацепа
rope.Attachment1 = a1
-- толщина
rope.Width0 = 0.15
-- толщина
rope.Width1 = 0.15
-- всегда видна
rope.FaceCamera = true
-- коричневая
rope.Color = ColorSequence.new(Color3.fromRGB(70, 50, 35))
-- показываем
rope.Parent = hook
-- точка тяги
local ra = Instance.new("Attachment")
-- в центр персонажа
ra.Parent = root
-- тяга к зацепу
local pull = Instance.new("LinearVelocity")
-- тянем персонажа
pull.Attachment0 = ra
-- без ограничения силы
pull.MaxForce = math.huge
-- включаем
pull.Parent = root
-- время начала
local start = os.clock()
-- пока не долетели (не дольше 3 с)
while (hook.Position - root.Position).Magnitude > 4 and os.clock() - start < 3 and humanoid.Health > 0 and tool.Parent == character do
-- летим прямо к зацепу
pull.VectorVelocity = (hook.Position - root.Position).Unit * PULL_SPEED
-- кадр
RunService.Heartbeat:Wait()
-- конец цикла
end
-- тяга кончилась
pull:Destroy()
-- точка тоже
ra:Destroy()
-- зацеп и верёвка
hook:Destroy()
-- начало верёвки
a0:Destroy()
-- небольшой подскок — забраться на край
root.AssemblyLinearVelocity = Vector3.new(0, 25, 0)
-- можно снова
busy = false
-- конец обработчика
end)Запусти Play (или Run) и убедись: