Загрузка данных
local Players = game:GetService("Players")
local RunService = game:GetService("RunService")
local UserInputService = game:GetService("UserInputService")
-- ================= НАСТРОЙКИ =================
local Settings = {
-- Камера
CameraOffset = Vector3.new(0, -0.25, -1.5), -- позиция камеры относительно головы
FieldOfView = 100,
SprintFOV = 108, -- FOV при беге
-- Движение
WalkSpeed = 16,
SprintSpeed = 26,
SprintKey = Enum.KeyCode.LeftShift, -- бег
ToggleCameraKey = Enum.KeyCode.F, -- выход из / вход в режим камеры
-- Покачивание
BobEnabled = true,
BobVertical = 0.12, -- вверх-вниз
BobHorizontal = 0.08, -- влево-вправо
BobSpeed = 0.35, -- частота шагов
SprintBobMultiplier = 1.5, -- во сколько раз сильнее при беге
BobSmoothing = 10, -- плавность
-- Третье лицо (после нажатия F)
ThirdPersonMinZoom = 10,
ThirdPersonMaxZoom = 400,
-- Видимость тела
ViewAccessories = false,
ViewModels = false,
HeadLocalTransparency = 0, -- 0 = голова остаётся (камера стоит перед ней, её не видно, тень есть); 1 = полностью скрыть
}
-- =============================================
local player = Players.LocalPlayer
local camera = workspace.CurrentCamera
local character, humanoid, root
local firstPerson = true
local sprinting = false
local bobTime = 0
local bobOffset = Vector3.zero
local locked = {}
local function classify(part)
if not part:IsA("BasePart") or not character then return nil end
if part.Name == "Head" and part.Parent == character then
return Settings.HeadLocalTransparency
end
if part:FindFirstAncestorOfClass("Accessory") then
return Settings.ViewAccessories and 0 or nil
end
if part.Parent == character then
return 0
end
if part:FindFirstAncestorOfClass("Model") ~= character and Settings.ViewModels then
return 0
end
return nil
end
local function register(part)
local value = classify(part)
if value ~= nil then
locked[part] = value
end
end
local function applyMode()
if not humanoid then return end
if firstPerson then
player.CameraMode = Enum.CameraMode.LockFirstPerson
player.CameraMinZoomDistance = 0.5
player.CameraMaxZoomDistance = 0.5 -- зум заблокирован, камера не съезжает
else
player.CameraMode = Enum.CameraMode.Classic
player.CameraMinZoomDistance = Settings.ThirdPersonMinZoom
player.CameraMaxZoomDistance = Settings.ThirdPersonMaxZoom
humanoid.CameraOffset = Vector3.zero
camera.FieldOfView = 70
for part in pairs(locked) do
part.LocalTransparencyModifier = 0
end
end
end
local function setupCharacter(char)
character = char
humanoid = char:WaitForChild("Humanoid")
root = char:WaitForChild("HumanoidRootPart")
locked = {}
sprinting = false
bobTime = 0
bobOffset = Vector3.zero
humanoid.WalkSpeed = Settings.WalkSpeed
for _, d in ipairs(char:GetDescendants()) do
register(d)
end
char.DescendantAdded:Connect(register)
char.DescendantRemoving:Connect(function(d)
locked[d] = nil
end)
applyMode()
end
-- Бег и переключение камеры
UserInputService.InputBegan:Connect(function(input, processed)
if processed or not humanoid then return end
if input.KeyCode == Settings.SprintKey then
sprinting = true
humanoid.WalkSpeed = Settings.SprintSpeed
elseif input.KeyCode == Settings.ToggleCameraKey then
firstPerson = not firstPerson
applyMode()
end
end)
UserInputService.InputEnded:Connect(function(input)
if input.KeyCode == Settings.SprintKey and humanoid then
sprinting = false
humanoid.WalkSpeed = Settings.WalkSpeed
end
end)
-- Каждый кадр после стандартной камеры Roblox
RunService:BindToRenderStep("FirstPersonBody", Enum.RenderPriority.Camera.Value + 1, function(dt)
if not humanoid or not root or humanoid.Health <= 0 or not firstPerson then return end
-- Тело видно (тени остаются)
for part, value in pairs(locked) do
part.LocalTransparencyModifier = value
end
-- Покачивание
local target = Vector3.zero
local flatVelocity = root.AssemblyLinearVelocity * Vector3.new(1, 0, 1)
local speed = flatVelocity.Magnitude
local onGround = humanoid.FloorMaterial ~= Enum.Material.Air
if Settings.BobEnabled and onGround and speed > 1 and humanoid.MoveDirection.Magnitude > 0 then
local mult = sprinting and Settings.SprintBobMultiplier or 1
bobTime += dt * speed * Settings.BobSpeed
target = Vector3.new(
math.sin(bobTime) * Settings.BobHorizontal * mult,
math.sin(bobTime * 2) * Settings.BobVertical * mult,
0
)
end
bobOffset = bobOffset:Lerp(target, math.clamp(dt * Settings.BobSmoothing, 0, 1))
humanoid.CameraOffset = Settings.CameraOffset + bobOffset
-- FOV (при беге чуть шире)
local targetFov = (sprinting and speed > 1) and Settings.SprintFOV or Settings.FieldOfView
camera.FieldOfView += (targetFov - camera.FieldOfView) * math.clamp(dt * 8, 0, 1)
end)
-- Камера не липнет к сиденьям
camera:GetPropertyChangedSignal("CameraSubject"):Connect(function()
if humanoid and camera.CameraSubject and camera.CameraSubject:IsA("VehicleSeat") then
camera.CameraSubject = humanoid
end
end)
player.CharacterAdded:Connect(setupCharacter)
if player.Character then
setupCharacter(player.Character)
end