Загрузка данных
local RunService = game:GetService("RunService")
local char = script.Parent
local humanoid = char:WaitForChild("Humanoid")
if humanoid.RigType ~= Enum.HumanoidRigType.R6 then return end
local root = char:WaitForChild("HumanoidRootPart")
local torso = char:WaitForChild("Torso")
-- Отключаем стандартную анимацию
local animate = char:WaitForChild("Animate", 3)
if animate then animate.Disabled = true end
local animator = humanoid:WaitForChild("Animator")
for _, track in ipairs(animator:GetPlayingAnimationTracks()) do
track:Stop(0)
end
animator.AnimationPlayed:Connect(function(track)
track:Stop(0)
end)
-- Суставы
local joints = {
root = root:WaitForChild("RootJoint"),
neck = torso:WaitForChild("Neck"),
rs = torso:WaitForChild("Right Shoulder"),
ls = torso:WaitForChild("Left Shoulder"),
rh = torso:WaitForChild("Right Hip"),
lh = torso:WaitForChild("Left Hip"),
}
local base = {}
for name, joint in pairs(joints) do
base[name] = joint.C0
end
-- Настройки
local STRIDE_SPEED = 0.6 -- частота шага относительно скорости
local LEG_SWING = 0.85 -- размах ног
local ARM_SWING = 0.7 -- размах рук
local TORSO_TWIST = 0.14 -- поворот корпуса при шаге
local TORSO_LEAN = 0.07 -- наклон вперёд при движении
local SMOOTHNESS = 10 -- плавность переходов между позами
-- Текущая и целевая позы
local function newPose()
return {
rootPitch = 0, rootRoll = 0, rootTwist = 0,
neckPitch = 0, neckRoll = 0, neckYaw = 0,
rs = 0, ls = 0, rh = 0, lh = 0, -- положительное значение = вперёд
}
end
local cur = newPose()
local phase = 0
local idleTime = 0
local camBob = 0
RunService.RenderStepped:Connect(function(dt)
if humanoid.Health <= 0 then return end
local vel = root.AssemblyLinearVelocity
local speed = Vector3.new(vel.X, 0, vel.Z).Magnitude
local state = humanoid:GetState()
local airborne = state == Enum.HumanoidStateType.Freefall
or state == Enum.HumanoidStateType.Jumping
local target = newPose()
local bobTarget = 0
if airborne then
local rising = vel.Y > 0
target.rs = rising and 1.1 or 0.5
target.ls = rising and 1.1 or 0.5
target.rh = 0.35
target.lh = -0.25
target.rootPitch = rising and -0.05 or 0.04
elseif speed > 0.5 then
local k = math.clamp(speed / 16, 0.2, 1.4)
phase += dt * speed * STRIDE_SPEED
local s = math.sin(phase)
local c = math.cos(phase)
-- Ноги в противофазе
target.rh = s * LEG_SWING * k
target.lh = -s * LEG_SWING * k
-- Руки машут навстречу ногам
target.rs = -s * ARM_SWING * k
target.ls = s * ARM_SWING * k
-- Корпус: наклон, скручивание и лёгкое покачивание
target.rootPitch = TORSO_LEAN * k
target.rootTwist = s * TORSO_TWIST * k
target.rootRoll = c * 0.035 * k
-- Голова компенсирует поворот корпуса
target.neckYaw = -target.rootTwist * 0.8
target.neckRoll = -target.rootRoll * 0.6
target.neckPitch = -TORSO_LEAN * k * 0.7
bobTarget = (math.abs(s) - 0.5) * 0.14 * k
else
-- Стойка: дыхание и лёгкое покачивание
idleTime += dt
local breathe = math.sin(idleTime * 1.6)
local sway = math.sin(idleTime * 0.7)
target.rootPitch = 0.015 * breathe
target.rootRoll = 0.012 * sway
target.rootTwist = 0.02 * sway
target.rs = 0.05 + 0.04 * breathe
target.ls = 0.05 + 0.04 * breathe
target.rh = 0.02
target.lh = -0.02
target.neckPitch = -0.02 * breathe
target.neckYaw = 0.06 * math.sin(idleTime * 0.45)
target.neckRoll = -0.012 * sway
end
-- Плавный переход к целевой позе
local alpha = 1 - math.exp(-dt * SMOOTHNESS)
for key, value in pairs(target) do
cur[key] += (value - cur[key]) * alpha
end
camBob += (bobTarget - camBob) * alpha
humanoid.CameraOffset = Vector3.new(0, camBob, 0)
-- Применяем к суставам
joints.root.C0 = base.root * CFrame.Angles(cur.rootPitch, cur.rootRoll, cur.rootTwist)
joints.neck.C0 = base.neck * CFrame.Angles(cur.neckPitch, cur.neckRoll, cur.neckYaw)
joints.rs.C0 = base.rs * CFrame.Angles(0, 0, cur.rs)
joints.ls.C0 = base.ls * CFrame.Angles(0, 0, -cur.ls)
joints.rh.C0 = base.rh * CFrame.Angles(0, 0, cur.rh)
joints.lh.C0 = base.lh * CFrame.Angles(0, 0, -cur.lh)
end)