Roblox · Движение

Подкат на Ctrl

На бегу жмёшь Ctrl (или C) — персонаж пригибается и скользит вперёд. Под низкими препятствиями (папка SlideUnder) в подкате можно проскользнуть.

Структура

Синим — что нужно создать.

StarterPlayer
└─ StarterPlayerScripts
   └─ SlideLocal (LocalScript)
      └─ Animation (Animation) — анимация подката (можно пусто)
Workspace
└─ SlideUnder (Folder) — низкие препятствия: CollisionGroup = SlideUnder
Модель → Collision Groups — Sliding и SlideUnder друг с другом не сталкиваются

Шаги

  1. Model → Collision Groups: создай группы «Sliding» и «SlideUnder», сними галочку на их пересечении.
  2. Препятствия, под которыми можно проскользнуть (низкая балка, щель под стеной): Workspace → Folder «SlideUnder», у каждой детали CollisionGroup = SlideUnder. Балку ставь на высоте 2–3 studs над полом.
  3. StarterPlayerScripts → LocalScript «SlideLocal», внутри Animation (AnimationId подката — по желанию).
  4. Как работает: на время подката все детали персонажа переходят в группу Sliding (сквозь SlideUnder), HipHeight уменьшается — персонаж ниже, а LinearVelocity толкает вперёд только по земле.
  5. Клавиша назначена через ContextActionService — на телефоне сама появляется кнопка «Подкат».

Скрипты

SlideLocal

Где: StarterPlayer → StarterPlayerScripts · LocalScript
Зачем: Подкат: толчок, пригибание, проход под препятствиями.

-- клавиши и кнопки на телефоне
local CAS = game:GetService("ContextActionService")
-- этот игрок
local player = game.Players.LocalPlayer
-- анимация подката (можно пустую)
local anim = script:WaitForChild("Animation")
-- скорость скольжения
local SLIDE_SPEED = 45
-- сколько секунд скользим
local SLIDE_TIME = 0.6
-- во сколько раз опускается персонаж (HipHeight)
local LOW = 0.4
-- секунд до следующего подката
local COOLDOWN = 1
-- время прошлого подката
local last = 0

-- Ctrl или C (на телефоне — кнопка «Подкат»)
CAS:BindAction("Slide", function(_, state)
    -- только нажатие
    if state ~= Enum.UserInputState.Begin 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
    -- подкат — только на бегу
    if humanoid.MoveDirection.Magnitude < 0.1 then return end
    -- и только на земле
    if humanoid.FloorMaterial == Enum.Material.Air then return end
    -- откат
    if os.clock() - last < COOLDOWN then return end
    -- запоминаем
    last = os.clock()
    -- куда бежал — по земле
    local dir = (humanoid.MoveDirection * Vector3.new(1, 0, 1)).Unit
    -- прежние группы коллизий деталей
    local groups = {}
    -- все детали персонажа
    for _, part in ipairs(character:GetDescendants()) do
        -- деталь
        if part:IsA("BasePart") then
            -- запоминаем группу
            groups[part] = part.CollisionGroup
            -- группа Sliding проходит сквозь препятствия SlideUnder
            part.CollisionGroup = "Sliding"
        -- конец проверки
        end
    -- конец перебора
    end
    -- обычная высота
    local hip = humanoid.HipHeight
    -- персонаж пригибается
    humanoid.HipHeight = hip * LOW
    -- анимация
    local track = nil
    -- задана
    if anim.AnimationId ~= "" then
        -- загружаем
        track = humanoid:WaitForChild("Animator"):LoadAnimation(anim)
        -- играем
        track:Play()
    -- конец проверки
    end
    -- точка приложения
    local attachment = Instance.new("Attachment")
    -- в центр персонажа
    attachment.Parent = root
    -- толчок вперёд
    local push = Instance.new("LinearVelocity")
    -- куда приложен
    push.Attachment0 = attachment
    -- сила отдельно по осям
    push.ForceLimitMode = Enum.ForceLimitMode.PerAxis
    -- только по земле — падать не мешает
    push.MaxAxesForce = Vector3.new(100000, 0, 100000)
    -- скорость скольжения
    push.VectorVelocity = dir * SLIDE_SPEED
    -- толкаем
    push.Parent = root
    -- скользим
    task.wait(SLIDE_TIME)
    -- толчок кончился
    push:Destroy()
    -- точка тоже
    attachment:Destroy()
    -- анимация
    if track then track:Stop() end
    -- встаём
    humanoid.HipHeight = hip
    -- все детали
    for part, group in pairs(groups) do
        -- прежняя группа — снова сталкиваемся
        if part.Parent then part.CollisionGroup = group end
    -- конец перебора
    end
-- true — кнопка на телефоне
end, true, Enum.KeyCode.LeftControl, Enum.KeyCode.C)
-- надпись на кнопке
CAS:SetTitle("Slide", "Подкат")

Проверка

Запусти Play (или Run) и убедись:

Собрать подкат одной командой