Загрузка данных


-- Настройки
local isTesting = false -- Сделал название без пробела для корректной работы
local minDistance = -10 
local maxDistance = 4 
local rigidness = 0.6 

-- Ссылки на объекты
local runService = game:GetService("RunService")
local player = game.Players.LocalPlayer
local character = script.Parent
local humanoid = character:WaitForChild("Humanoid")
local rootPart = character:WaitForChild("HumanoidRootPart")
local head = character:WaitForChild("Head")

-- Создание детали CamPart
local camPart = Instance.new("Part")
camPart.Name = "CamPart"
camPart.CanCollide = false
camPart.Anchored = true
camPart.Shape = Enum.PartType.Ball
camPart.Size = Vector3.new(1, 1, 1) -- Уменьшил размер, чтобы не мешал

if not isTesting then 
	camPart.Transparency = 1
	camPart.Parent = character
else
	camPart.Color = Color3.fromRGB(0, 255, 0)
	camPart.Parent = workspace
	
	local highlight = Instance.new("Highlight")
	highlight.Parent = camPart
	highlight.FillColor = Color3.new(0, 0, 1)
end

-- Изначальная позиция
camPart.CFrame = head.CFrame

runService.RenderStepped:Connect(function(dt)
	local camera = workspace.CurrentCamera
	if not camera then return end

	-- Защита от "улетания" координат (NaN или бесконечность)
	if camPart.Position.Magnitude > 10000 then
		camPart.CFrame = head.CFrame
	end

	-- Плавное движение CamPart к голове персонажа
	-- Используем (1 - math.exp(-rigidness * dt * 10)) для идеально плавного Lerp при любом FPS
	local alpha = math.clamp(rigidness * dt * 10, 0, 1)
	camPart.Position = camPart.Position:Lerp(head.Position, alpha)
	
	-- Поворачиваем CamPart в сторону головы
	camPart.CFrame = camPart.CFrame:Lerp(CFrame.lookAt(camPart.Position, head.Position), alpha)

	-- Вычисляем локальное смещение относительно RootPart
	-- Это критический момент: мы смотрим, где находится CamPart относительно торса
	local relativeVector = rootPart.CFrame:PointToObjectSpace(camPart.Position)
	
	-- Коррекция высоты (так как камера обычно на уровне глаз, а не в центре торса)
	local offset = relativeVector - Vector3.new(0, 1.5, 0)

	-- Ограничение дистанции
	local clampedX = math.clamp(offset.X, minDistance, maxDistance)
	local clampedY = math.clamp(offset.Y, minDistance, maxDistance)
	local clampedZ = math.clamp(offset.Z, minDistance, maxDistance)

	-- Применяем смещение к камере через Humanoid
	humanoid.CameraOffset = Vector3.new(clampedX, clampedY, clampedZ)

	-- Логика "доворота" камеры, если смещение слишком большое
	if offset.Magnitude > maxDistance / 2 then
		local lookTarget = camera.CFrame:Lerp(CFrame.lookAt(camera.CFrame.Position, head.Position), 0.1)
		camera.CFrame = camera.CFrame:Lerp(lookTarget, alpha)
	end
end)