How can I make the camera adjust to the rotation of the part the player is standing on?

on that video, you can see, what camera always on center if you go forward, and if you go backward, your camera gets on top of screen, aslo it snaps parts or i dont know how else

I know it sounds cringy but
I tried to integrate this into my script with ai and it looks pretty ahh i gues..

local Player = game:GetService("Players").LocalPlayer
local Mouse = Player:GetMouse()
local Camera = game:GetService("Workspace").CurrentCamera
local UserInputService = game:GetService("UserInputService")
local Humanoid = Player.Character:WaitForChild("Humanoid")

local settingS = script.Parent.settings
local setPos = settingS.Position
local setPosEnd = setPos - UDim2.new(0, 0, 1.5, 0)

local bobbing = nil
local func1 = 0
local func2 = 0
local func3 = 0
local func4 = 0
local val = 0
local val2 = 0
local int = 2
local int2 = 2

CanViewBody = true

repeat
	wait()
	Camera.CameraType = Enum.CameraType.Custom
until
Camera.CameraType == Enum.CameraType.Custom

local vect3 = Vector3.new()
local character = Player.Character

UserInputService.MouseIconEnabled = false

local tweenservice = game:GetService("TweenService")

local tweeninfo = TweenInfo.new(
	0.4,
	Enum.EasingStyle.Back,
	Enum.EasingDirection.InOut,
	0,
	false,
	0
)

function lerp(a, b, c)
	return a + (b - a) * c
end

local UserInputService = game:GetService("UserInputService")
local RunService = game:GetService("RunService")

local settingS = script.Parent:WaitForChild("settings")
local startPos = UDim2.new(0.499, 0,9.498, 0)
local endPos = UDim2.new(0.499, 0,0.498, 0)
local animationDuration = 0.5
local overshootAmount = 0.3
local isOpen = false

local function backInOut(t, overshoot)
	if t < 0.5 then
		t = 2 * t
		return 0.5 * (t * t * ((overshoot + 1) * t - overshoot))
	else
		t = 2 * t - 2
		return 0.5 * (t * t * ((overshoot + 1) * t + overshoot) + 2)
	end
end

local function animateWithOvershoot(guiElement, fromPos, toPos, duration, overshoot)
	local elapsedTime = 0
	local connection

	connection = RunService.RenderStepped:Connect(function(deltaTime)
		elapsedTime = elapsedTime + deltaTime
		local t = math.clamp(elapsedTime / duration, 0, 1)

		local progress = backInOut(t, overshoot)

		guiElement.Position = fromPos:Lerp(toPos, progress)

		if t >= 1 then
			connection:Disconnect()
		end
	end)
end

UserInputService.InputBegan:Connect(function(input, gameProcessedEvent)
	if input.KeyCode == Enum.KeyCode.Tab then
		if not isOpen then
			settingS.Visible = true
			UserInputService.MouseIconEnabled = true
			animateWithOvershoot(settingS, startPos, endPos, animationDuration, overshootAmount)
			isOpen = true
		else
			animateWithOvershoot(settingS, endPos, startPos, animationDuration, overshootAmount)
			task.wait(animationDuration)
			UserInputService.MouseIconEnabled = false
			settingS.Visible = false
			isOpen = false
		end
	end
end)

local currentTiltPitch = 0
local currentTiltRoll = 0
local tiltSmoothness = 0.01 

local function getSurfaceTilt()
	local rootPart = Humanoid.RootPart
	if not rootPart then return 0, 0 end

	local origin = rootPart.Position + Vector3.new(0, 0.5, 0)
	local raycastParams = RaycastParams.new()
	raycastParams.FilterType = Enum.RaycastFilterType.Blacklist
	raycastParams.FilterDescendantsInstances = {character}

	local raycastResult = workspace:Raycast(origin, Vector3.new(0, -3, 0), raycastParams)
	if not raycastResult then return 0, 0 end

	local groundNormal = raycastResult.Normal
	local worldUp = Vector3.new(0, 1, 0)

	if (groundNormal - worldUp).Magnitude < 0.01 then
		return 0, 0
	end

	local targetPitch = -groundNormal.Z * 0.4 
	local targetRoll = groundNormal.X * 0.3 

	local moveDirection = Humanoid.MoveDirection
	local isMoving = moveDirection.Magnitude > 0.1

	if isMoving then
		if moveDirection.Z < -0.5 then
			targetPitch = targetPitch - 0.15
		end
	end

	return targetPitch, targetRoll
end

bobbing = RunService.RenderStepped:Connect(function(deltaTime)
	if Humanoid.Health <= 0 then
		bobbing:Disconnect()
		return
	end

	deltaTime = deltaTime * 30
	local rootMagnitude = Humanoid.RootPart and Vector3.new(Humanoid.RootPart.Velocity.X, 0, Humanoid.RootPart.Velocity.Z).Magnitude or 0
	local calcRootMagnitude = math.min(rootMagnitude, 25)

	if deltaTime > 1.5 then
		func1 = 0
		func2 = 0
	else
		func1 = lerp(func1, math.cos(tick() * 0.5 * math.random(5, 7.5)) * (math.random(2.5, 10) / 100) * deltaTime, 0.05 * deltaTime)
		func2 = lerp(func2, math.cos(tick() * 0.5 * math.random(2.5, 5)) * (math.random(1, 5) / 100) * deltaTime, 0.05 * deltaTime)
	end

	local targetPitch, targetRoll = getSurfaceTilt()

	currentTiltPitch = lerp(currentTiltPitch, targetPitch, tiltSmoothness)
	currentTiltRoll = lerp(currentTiltRoll, targetRoll, tiltSmoothness)

	local surfaceTiltCFrame = CFrame.Angles(currentTiltPitch, 0, currentTiltRoll)

	local combinedEffects = 
		CFrame.fromEulerAnglesXYZ(0, 0, math.rad(func3)) * 
		CFrame.fromEulerAnglesXYZ(math.rad(func4 * deltaTime), math.rad(val * deltaTime), val2) * 
		CFrame.Angles(0, 0, math.rad(func4 * deltaTime * (calcRootMagnitude / 5))) * 
		CFrame.fromEulerAnglesXYZ(math.rad(func1), math.rad(func2), math.rad(func2 * 10)) *
		surfaceTiltCFrame

	Camera.CFrame = Camera.CFrame * combinedEffects

	val2 = math.clamp(lerp(val2, -Camera.CFrame:VectorToObjectSpace((Humanoid.RootPart and Humanoid.RootPart.Velocity or Vector3.new()) / math.max(Humanoid.WalkSpeed, 0.01)).X * 0.04, 0.1 * deltaTime), -0.12, 0.1)
	func3 = lerp(func3, math.clamp(UserInputService:GetMouseDelta().X, -2.5, 2.5), 0.25 * deltaTime)
	func4 = lerp(func4, math.sin(tick() * int) / 5 * math.min(1, int2 / 10), 0.25 * deltaTime)

	if rootMagnitude > 1 then
		val = lerp(val, math.cos(tick() * 0.5 * math.floor(int)) * (int / 200), 0.25 * deltaTime)
	else
		val = lerp(val, 0, 0.05 * deltaTime)
	end

	if rootMagnitude > 6 then
		int = 10
		int2 = 9
	elseif rootMagnitude > 0.1 then
		int = 6
		int2 = 7
	else
		int2 = 0
	end

	vect3 = lerp(vect3, Camera.CFrame.LookVector, 0.125 * deltaTime)
end)

for _, v in pairs(character:GetChildren()) do
	if v:IsA("BasePart") and v.Name ~= "Head" then
		v.CastShadow = false
	end    
end

function senschange()
	UserInputService.MouseDeltaSensitivity = script.Sens.Value
end

script.Sens.Changed:Connect(senschange)

wait(0.1)
task.spawn(senschange)

It works really ahh and i dont know why, because ai made it really weird and i cant see so much in it.

3 Likes