Бег по стенам, подкаты и преодоление препятствий формируют динамику современных игр. Попытки сделать это на стандартном Humanoid приводят к застреваниям и потере скорости.
Используя новые физические ограничения Luau (`LinearVelocity` и `VectorForce`) вместе с лучами Raycast, вы создадите отзывчивую систему перемещения консольного качества для всех платформ.
1. Переопределение Состояний Humanoid для Плавного Паркура
Построение конечного автомата состояний перемещения:
- Отключение Конфликтных Состояний: При входе в бег по стене отключите стандартное лазание и свободное падение, чтобы анимации не сбивали расчеты.
- Сетевой Владелец (Network Owner): На сервере закрепите RootPart за клиентом для моментального отклика на клавиши управления.
- Модульный Автомат: Разделите поведение на ходьбу, спринт, бег по стене, вис на уступе и подтягивание с событиями входа и выхода.
2. Направленные Лучи Raycast и Нормали Поверхностей
Поиск стен и математика направления бега:
- Боковые Лучи-Датчики: Горизонтальные лучи от бедер и плеч (длиной 3,5 студа) мгновенно определяют приближение к стене.
- Проверка Наклона: Убедитесь, что нормаль перпендикулярна земле (угол от 75° до 105°), чтобы исключить бег по пологим горкам.
- Векторное Произведение: Направление движения вперед вдоль стены вычисляется как
wallNormal:Cross(Vector3.yAxis).
3. Физические Ограничения: LinearVelocity и VectorForce
Замена устаревших BodyMovers на современные констрейнты:
- LinearVelocity для Постоянной Скорости: Обеспечивает непрерывный импульс вперед, преодолевая трение о стену.
- VectorForce Антигравитации: Компенсирует ускорение свободного падения (196,2 студа/с²) силой, рассчитанной по массе аватара.
- Плавное Снижение Силы: Через 1,5–2 секунды подъемная сила начинает угасать, создавая естественное соскальзывание вниз.
-- Клиентский контроллер бега по стенам
local RunService = game:GetService("RunService")
local WallRun = {}
WallRun.__index = WallRun
function WallRun.new(character)
local self = setmetatable({}, WallRun)
self.Char = character
self.RootPart = character:WaitForChild("HumanoidRootPart")
self.Humanoid = character:WaitForChild("Humanoid")
local att = Instance.new("Attachment", self.RootPart)
local lv = Instance.new("LinearVelocity")
lv.Attachment0 = att
lv.MaxForce = 15000
lv.RelativeTo = Enum.ActuatorRelativeTo.World
lv.Enabled = false
lv.Parent = self.RootPart
self.Attachment = att
self.LinearVelocity = lv
self.IsRunning = false
return self
end
function WallRun:CheckWall(side)
local rightVec = self.RootPart.CFrame.RightVector
local rayDir = (side == "Left" and -rightVec or rightVec) * 3.5
local params = RaycastParams.new()
params.FilterDescendantsInstances = {self.Char}
params.FilterType = Enum.RaycastFilterType.Exclude
return workspace:Raycast(self.RootPart.Position, rayDir, params)
end
function WallRun:Start(hitNormal, forwardDir)
self.IsRunning = true
self.LinearVelocity.VectorVelocity = forwardDir * 32 + Vector3.new(0, 4, 0)
self.LinearVelocity.Enabled = true
self.Humanoid:ChangeState(Enum.HumanoidStateType.Physics)
end
function WallRun:Stop()
self.IsRunning = false
self.LinearVelocity.Enabled = false
self.Humanoid:ChangeState(Enum.HumanoidStateType.Freefall)
end
return WallRun
4. Определение Уступов и Залезание (Mantle)
Захват кромок и плавное преодоление преград:
- Двухуровневый Raycast: Луч на уровне груди находит стену, а вертикальный луч сверху определяет точный край уступа.
- Фиксация через AlignPosition: В момент хвата персонаж притягивается к краю и зависает на руках.
- Подъем по Кривой Безье: По нажатию прыжка RootPart плавно поднимается и переносится через край по дуге.
5. Мобильное Управление и Серверная Защита от Читов
Удобство на смартфонах и безопасность игрового процесса:
- Крупные Сенсорные Кнопки: Прыжок от стены и карабканье привязываются к экранным кнопкам размером от 48x48 пикселей.
- Проверка Скорости на Сервере: Сервер вычисляет дистанцию за кадр и пресекает телепортацию и полеты.
- Верификация Наличия Стены: Сервер пускает собственный луч, подтверждая, что игрок действительно бежал вдоль стены.
Frequently Asked Questions
Почему нужно использовать LinearVelocity вместо BodyVelocity?
BodyVelocity устарел и не поддерживается. LinearVelocity работает на новом движке ограничений, учитывает массу и дает высокую стабильность.
Как избежать падения со стены во время бега?
Создать направленную вверх силу VectorForce, равную массе персонажа, умноженной на гравитацию мира.
Как рассчитывается вектор движения вдоль стены?
Через векторное произведение нормали стены и глобального вектора верха (0, 1, 0).
Как сервер защищает механику бега по стенам от читеров?
Сервер сам пускает Raycast для проверки наличия стены и контролирует предельную скорость перемещения.