Загрузка данных
-- REALISTIC CAMERA - FIXED
-- CTRL = бег | F = переключение камеры
local Players = game:GetService("Players")
local UIS = game:GetService("UserInputService")
local RunService = game:GetService("RunService")
local player = Players.LocalPlayer
-- НАСТРОЙКИ
local WALK_SPEED = 16
local SPRINT_SPEED = 25
local NORMAL_FOV = 90
local SPRINT_FOV = 120
-- ПОКАЧИВАНИЕ ПРИ ХОДЬБЕ
local WALK_X = 0.045
local WALK_Y = 0.065
-- ПОКАЧИВАНИЕ ПРИ БЕГЕ
local RUN_X = 0.09
local RUN_Y = 0.13
local BOB_SMOOTHNESS = 9
local FOV_SMOOTHNESS = 5
-- СОСТОЯНИЕ
local character
local humanoid
local firstPerson = true
local sprintHeld = false
local bobTime = 0
local sprintTime = 0
local fatigue = 0
local currentOffset = Vector3.zero
local currentRoll = 0
-- КАМЕРА
local function setCameraMode(enabled)
firstPerson = enabled
if enabled then
player.CameraMode = Enum.CameraMode.LockFirstPerson
player.CameraMinZoomDistance = 0.5
player.CameraMaxZoomDistance = 0.5
else
player.CameraMode = Enum.CameraMode.Classic
player.CameraMinZoomDistance = 0.5
player.CameraMaxZoomDistance = 12
end
end
-- СКОРОСТЬ
local function updateSpeed()
if not humanoid or humanoid.Health <= 0 then
return
end
humanoid.WalkSpeed = sprintHeld and SPRINT_SPEED or WALK_SPEED
end
-- ПЕРСОНАЖ
local function setupCharacter(char)
character = char
humanoid = char:WaitForChild("Humanoid")
sprintHeld = false
bobTime = 0
sprintTime = 0
fatigue = 0
currentOffset = Vector3.zero
currentRoll = 0
humanoid.WalkSpeed = WALK_SPEED
setCameraMode(firstPerson)
end
-- КЛАВИАТУРА
UIS.InputBegan:Connect(function(input, processed)
if input.KeyCode == Enum.KeyCode.LeftControl
or input.KeyCode == Enum.KeyCode.RightControl then
sprintHeld = true
updateSpeed()
return
end
if processed then
return
end
if input.KeyCode == Enum.KeyCode.F then
setCameraMode(not firstPerson)
end
end)
UIS.InputEnded:Connect(function(input)
if input.KeyCode == Enum.KeyCode.LeftControl
or input.KeyCode == Enum.KeyCode.RightControl then
sprintHeld = false
updateSpeed()
end
end)
UIS.WindowFocusReleased:Connect(function()
sprintHeld = false
updateSpeed()
end)
-- ПОДДЕРЖАНИЕ СКОРОСТИ
RunService.Heartbeat:Connect(function()
if humanoid and humanoid.Health > 0 then
local target = sprintHeld and SPRINT_SPEED or WALK_SPEED
if humanoid.WalkSpeed ~= target then
humanoid.WalkSpeed = target
end
end
end)
-- КАМЕРА: ВАЖНО — ПОСЛЕ СТАНДАРТНОГО ОБНОВЛЕНИЯ ROBLOX
pcall(function()
RunService:UnbindFromRenderStep("RealisticCameraFixed")
end)
RunService:BindToRenderStep(
"RealisticCameraFixed",
Enum.RenderPriority.Camera.Value + 1,
function(dt)
local camera = workspace.CurrentCamera
if not camera then
return
end
local alive = humanoid and humanoid.Health > 0
local moving = alive
and humanoid.MoveDirection.Magnitude > 0.05
local running = moving and sprintHeld
-- FOV
local targetFOV = sprintHeld and SPRINT_FOV or NORMAL_FOV
local fovAlpha = 1 - math.exp(-FOV_SMOOTHNESS * dt)
camera.FieldOfView +=
(targetFOV - camera.FieldOfView) * fovAlpha
-- УСТАЛОСТЬ
if running then
sprintTime += dt
else
sprintTime = 0
end
local targetFatigue = math.clamp(
(sprintTime - 90) / 30,
0,
1
)
local fatigueAlpha = 1 - math.exp(-1.5 * dt)
fatigue += (targetFatigue - fatigue) * fatigueAlpha
-- ПОКАЧИВАНИЕ
local targetOffset = Vector3.zero
local targetRoll = 0
if firstPerson and moving then
local frequency = sprintHeld and 12 or 8
bobTime += dt * frequency
local x = sprintHeld and RUN_X or WALK_X
local y = sprintHeld and RUN_Y or WALK_Y
local fatigueMultiplier = 1 + fatigue * 1.5
targetOffset = Vector3.new(
math.cos(bobTime * 0.5) * x * fatigueMultiplier,
math.abs(math.sin(bobTime)) * y * fatigueMultiplier,
0
)
-- ДЫХАНИЕ ПРИ ДЛИТЕЛЬНОМ БЕГЕ
if running then
targetOffset += Vector3.new(
0,
math.sin(sprintTime * 2.5) * fatigue * 0.035,
0
)
targetRoll = math.sin(bobTime * 0.5)
* math.rad(1.2)
* fatigue
end
else
bobTime = 0
end
-- ПЛАВНОСТЬ
local alpha = 1 - math.exp(-BOB_SMOOTHNESS * dt)
currentOffset = currentOffset:Lerp(targetOffset, alpha)
currentRoll += (targetRoll - currentRoll) * alpha
-- ПРИМЕНЯЕМ КАМЕРУ ПОСЛЕ ОБНОВЛЕНИЯ ROBLOX
camera.CFrame = camera.CFrame
* CFrame.new(currentOffset)
* CFrame.Angles(0, 0, currentRoll)
end
)
-- ЗАПУСК
player.CharacterAdded:Connect(setupCharacter)
if player.Character then
setupCharacter(player.Character)
end