How to make leaning work?

You can write your topic however you want, but you need to answer these questions:

  1. What do you want to achieve? Im trying to add a leaning to my viewmodel but it doesnt work

  2. What is the issue? Just leaning doesnt happen

  3. What solutions have you tried so far? Leaning is not a popular thing soo I couldnt find something usefull

After that, you should include more details if you have any. Try to make your topic as descriptive as possible, so that it’s easier for people to help you!

-------SERVİCES----------
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local RunService = game:GetService("RunService")
local Players = game:GetService("Players")
local UserInputService = game:GetService("UserInputService")
local TweenService = game:GetService("TweenService")

-----PLAYER-INSTANCES-----
local Player = Players.LocalPlayer
local Camera = game.Workspace.CurrentCamera
local PlayerGui = Player.PlayerGui
local GunGUI = PlayerGui:WaitForChild("GunGUI").Frame
local AmmoValues = GunGUI.AmmoValues

------MODULES-----
local EquipGunViewModel = require(ReplicatedStorage.Modules.EquipGunViewModel)
local BulletModule = require(ReplicatedStorage.Modules.BulletModule)
local SpringModule = require(ReplicatedStorage.Modules.SpringModule)

-------EVENTS---------
local BulletHandle = ReplicatedStorage.Events.BulletHandle
local ReloadGunCharacter = ReplicatedStorage.Events.ReloadGunCharacter

local LoadOut = require(Player.PlayerGui:WaitForChild("LoadOut").Slots)

---VARİABLES-----
local isHoldingMouseButton1 = false
local isAiming = false
local isReloading = false
local isLeaning = false

local leaningSide = nil
local canFire = true

local gunConfig
local CurrentGun = LoadOut.primary.Name
local CurrentAmmo

-----MATH-STUFF-IDK------------
local RecoilSpring = SpringModule.new()
local BobbingSpring = SpringModule.new()
local SwayingSpring = SpringModule.new()

local updatedRecoilSpring = CFrame.new()
local updatedBobbingSpring = CFrame.new()
local updatedSwaySpring = CFrame.new()


ReplicatedStorage:FindFirstChild(LoadOut.viewmodel):Clone().Parent = game.Workspace.Camera
local ViewModel = Camera[LoadOut.viewmodel]

local function getBobbing(addition)
	return math.sin(tick() * addition * 1.3) * .5
end

BulletHandle.OnClientEvent:Connect(function(player, origin, endposition, gunName)
	if player ~= game.Players.LocalPlayer then
		task.spawn(function()
			print(gunName)
			for i,v in pairs(player.Character:WaitForChild(gunName).Barrel:GetChildren()) do
				if v:IsA("ParticleEmitter") then
					v:Emit()
				elseif v:IsA("PointLight") then
					v.Enabled = true
					wait(.1)
					v.Enabled = false
				end
			end

			gunConfig.fireSound:Play()
		end)
		local sentByOrigin = false
		BulletModule.bullet(player, origin, endposition, gunConfig, sentByOrigin)
	end
end)


RunService.RenderStepped:Connect(function(deltaTime)
	local Bobbing = Vector3.new(getBobbing(10), getBobbing(5), getBobbing(5))
	local Character = Player.Character or Player.CharacterAdded:Wait()
	local MouseDelta = UserInputService:GetMouseDelta()

	BobbingSpring:shove(Bobbing / 20 * (Character.HumanoidRootPart.Velocity.Magnitude) / 20)
	SwayingSpring:shove(Vector3.new(-MouseDelta.X / 500, MouseDelta.Y / 200, 0))

	ViewModel.FakeCamera.CFrame = game.Workspace.Camera.CFrame:ToWorldSpace(CFrame.new(updatedBobbingSpring.Y, updatedBobbingSpring.X, 0)) * CFrame.Angles(math.rad(updatedRecoilSpring.X)*4, 0, 0)
	Camera.CFrame = Camera.CFrame * CFrame.Angles(math.rad(updatedRecoilSpring.X), math.rad(updatedRecoilSpring.Y), math.rad(updatedRecoilSpring.Z))
	ViewModel.FakeCamera.CFrame *= CFrame.new(updatedSwaySpring.X, updatedSwaySpring.Y, 0)
	
	
	
	if isLeaning == true then
		if leaningSide == "Right" then
		else
			ViewModel.FakeCamera.CFrame = ViewModel.FakeCamera.CFrame:Lerp(ViewModel.FakeCamera.CFrame * CFrame.Angles(0, 0, math.rad(45)), 0.1)
			Camera.CFrame = Camera.CFrame:Lerp(ViewModel.FakeCamera.CFrame * CFrame.Angles(0, 0, math.rad(45)), 0.1) --This part is for Leaning but it doesnt make it really work like aiming idk how to explain check the video
		
		end
	end



	--- Aiming part as I said works smoothly
	if isAiming == true then
		ViewModel.FakeCamera.Position = ViewModel.FakeCamera.Position:Lerp(ViewModel[CurrentGun].AimPart.Position, 0.2)
	else
		ViewModel.FakeCamera.Position = ViewModel.FakeCamera.Position:Lerp(ViewModel.HumanoidRootPart.Position, 0.1)
	end

	updatedRecoilSpring = RecoilSpring:update(deltaTime)
	updatedBobbingSpring = BobbingSpring:update(deltaTime)
	updatedSwaySpring = SwayingSpring:update(deltaTime)
end)

RunService.Heartbeat:Connect(function(deltaTime)

	GunGUI.Mag.Text = gunConfig.magAmmo
	if isHoldingMouseButton1 == true then 
		if canFire == true and gunConfig.magAmmo ~= 0 and gunConfig.magAmmo > 0 and isReloading == false then

			if gunConfig.fireMode == "Semi" then
				isHoldingMouseButton1 = false
			end

			canFire = false
			RecoilSpring:shove(Vector3.new(gunConfig.UpRecoils[1],math.random(gunConfig.LeftRightRecoils[1],gunConfig.LeftRightRecoils[2])),gunConfig.RecoilShake)
			coroutine.wrap(function()
				wait(0.2)
				RecoilSpring:shove(Vector3.new(gunConfig.UpRecoils[2],math.random(gunConfig.WrapLeftRightRecoils[1],gunConfig.WrapLeftRightRecoils[2]),-gunConfig.RecoilShake))
			end)

			task.spawn(function()
				gunConfig.fireSound:Play()
				for i,v in pairs(ViewModel[CurrentGun].Barrel:GetChildren()) do
					if v:IsA("ParticleEmitter") then
						v:Emit()
					elseif v:IsA("PointLight") then
						v.Enabled = true
						wait(.1)
						v.Enabled = false
					end
				end
			end)
			
			local CastParams = RaycastParams.new()
			CastParams.IgnoreWater = true
			--CastParams.FilterType = Enum.RaycastFilterType.Blacklist
			CastParams.FilterDescendantsInstances = {ViewModel, game.Players.LocalPlayer.Character}
			local Mouse = BulletModule.getEndPos(1000,CastParams)
			BulletModule.bullet(Player, ViewModel[CurrentGun].Barrel.Position, Mouse, gunConfig, true)--sentByOrigin = true
			BulletHandle:FireServer(ViewModel[CurrentGun].Barrel.Position, Mouse, gunConfig, CurrentGun)
			
			gunConfig.magAmmo -= 1
			wait(gunConfig.fireDelay)
			canFire = true
		end    
	end
end)

--------------Start gun is prtimary incase 
EquipGunViewModel(ViewModel ,LoadOut.primary.Name, Player, CurrentGun, "Primary")
gunConfig = require(ViewModel[LoadOut.primary.Name].Config)
CurrentAmmo = AmmoValues.PrimaryMag.Value

UserInputService.InputBegan:Connect(function(input, gameProcessedEvent)
	if not gameProcessedEvent then
		if input.UserInputType == Enum.UserInputType.MouseButton1 then
			isHoldingMouseButton1 = true
		elseif input.UserInputType == Enum.UserInputType.MouseButton2 then
			isAiming = true
		end

		if input.KeyCode == Enum.KeyCode.One and CurrentGun ~= LoadOut.primary.Name then
			EquipGunViewModel(ViewModel, LoadOut.primary.Name, Player, CurrentGun, "Primary")
			CurrentGun = LoadOut.primary.Name
			gunConfig = require(ViewModel[LoadOut.primary.Name].Config)
		elseif input.KeyCode == Enum.KeyCode.Two and CurrentGun ~= LoadOut.secondary.Name then
			EquipGunViewModel(ViewModel, LoadOut.secondary.Name, Player, CurrentGun, "Secondary")
			CurrentGun = LoadOut.secondary.Name
			gunConfig = require(ViewModel[LoadOut.secondary.Name].Config)
		elseif input.KeyCode == Enum.KeyCode.Three and CurrentGun ~= LoadOut.melee.Name then
			EquipGunViewModel(ViewModel, LoadOut.melee.Name, Player, CurrentGun, "Melee")
			CurrentGun = LoadOut.melee.Name
			gunConfig = require(ViewModel[LoadOut.melee.Name].Config)
		elseif input.KeyCode == Enum.KeyCode.R then
			if CurrentAmmo ~= gunConfig.MaxAmmo then
				isReloading = true
				ViewModel.Humanoid:LoadAnimation(ReplicatedStorage.Animations.ViewModel.Reload.M416):Play()
				ReloadGunCharacter:FireServer(CurrentGun)
				
				wait(gunConfig.ReloadDelay)
				gunConfig.magAmmo = gunConfig.maxAmmo
				GunGUI.Mag.Text = gunConfig.maxAmmo
				isReloading = false
			end
		end
		
		if input.KeyCode == Enum.KeyCode.Q then-- LEANİNG
			if isLeaning == false then
				leaningSide = "Left"
				isLeaning = true
			elseif isLeaning == true and leaningSide == "Left" then
				isLeaning = false
			end
		elseif input.KeyCode == Enum.KeyCode.E then
		
		end
	end
end)

UserInputService.InputEnded:Connect(function(input: InputObject, gameProcessedEvent: boolean) 
	if gameProcessedEvent == false then
		if input.UserInputType == Enum.UserInputType.MouseButton1 then
			isHoldingMouseButton1 = false
		elseif input.UserInputType == Enum.UserInputType.MouseButton2 then
			isAiming = false
		end
	end
end)

Vİdeo: as you can see the aiming is smooth but leaning doesnt even happen ? idk bruh
Please do not ask people to write entire scripts or design entire systems for you. If you can’t answer the three questions above, you should probably pick a different category.

1 Like

I think what you wan’t to be doing is tweening the cameras CFrame using TweenService.
It goes something like this:

local TweenService  = game:GetService("TweenService")

local timeToLean    = 0.4 -- seconds
local info          = TweenInfo.new(timeToLean)
local leanAnimation = TweenService:Create(Camera, info, {CFrame = Camera.CFrame:Lerp(ViewModel.FakeCamera.CFrame * CFrame.Angles(0, 0, math.rad(45)), 0.1) })

leanAnimation:Play()

If you don’t know what TweenService is or forgot how it works, here is the Roblox documentation.

What about the Aiming and why is it better to use tweenservice ?

isn’t your aiming relative to your camera?

Aiming makes FakeCamera(ViewModels part that should where camera belongs) to go to guns AimPart. Also the solution doesnt work because it stops after the :Play()

Do you have discord or can you send the exact problem (and it’s probable cause)?

legendary.dev add me aaa. . … 123

Anyone else can explain WHY doesnt Cframe work ?

youre setting the position directly

use a tween if you want it to be smooth

I have it a go, let me know if this works.


-- Services
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local RunService = game:GetService("RunService")
local Players = game:GetService("Players")
local UserInputService = game:GetService("UserInputService")
local TweenService = game:GetService("TweenService")

-- Modules
local EquipGunViewModel = require(ReplicatedStorage.Modules.EquipGunViewModel)
local BulletModule = require(ReplicatedStorage.Modules.BulletModule)
local SpringModule = require(ReplicatedStorage.Modules.SpringModule)

-- Events
local BulletHandle = ReplicatedStorage.Events.BulletHandle
local ReloadGunCharacter = ReplicatedStorage.Events.ReloadGunCharacter

-- LoadOut
local LoadOut = require(Player.PlayerGui:WaitForChild("LoadOut").Slots)

-- Player
local Player = Players.LocalPlayer
local Camera = game.Workspace.CurrentCamera
local PlayerGui = Player.PlayerGui
local GunGUI = PlayerGui:WaitForChild("GunGUI").Frame
local AmmoValues = GunGUI.AmmoValues

-- ViewModel Setup
ReplicatedStorage:FindFirstChild(LoadOut.viewmodel):Clone().Parent = game.Workspace.Camera
local ViewModel = Camera[LoadOut.viewmodel]

-- Interface for InputHandler
local InputHandler = {}
InputHandler.__index = InputHandler

function InputHandler.new()
    local self = setmetatable({}, InputHandler)
    self.isHoldingMouseButton1 = false
    self.isAiming = false
    self.isReloading = false
    self.isLeaning = false
    self.leaningSide = nil
    self.canFire = true
    self.gunConfig = nil
    self.CurrentGun = LoadOut.primary.Name
    self.CurrentAmmo = AmmoValues.PrimaryMag.Value
    return self
end

function InputHandler:handleInputBegan(input: InputObject, gameProcessedEvent: boolean)
    if not gameProcessedEvent then
        if input.UserInputType == Enum.UserInputType.MouseButton1 then
            self.isHoldingMouseButton1 = true
        elseif input.UserInputType == Enum.UserInputType.MouseButton2 then
            self.isAiming = true
        end

        if input.KeyCode == Enum.KeyCode.One and self.CurrentGun ~= LoadOut.primary.Name then
            EquipGunViewModel(ViewModel, LoadOut.primary.Name, Player, self.CurrentGun, "Primary")
            self.CurrentGun = LoadOut.primary.Name
            self.gunConfig = require(ViewModel[LoadOut.primary.Name].Config)
        elseif input.KeyCode == Enum.KeyCode.Two and self.CurrentGun ~= LoadOut.secondary.Name then
            EquipGunViewModel(ViewModel, LoadOut.secondary.Name, Player, self.CurrentGun, "Secondary")
            self.CurrentGun = LoadOut.secondary.Name
            self.gunConfig = require(ViewModel[LoadOut.secondary.Name].Config)
        elseif input.KeyCode == Enum.KeyCode.Three and self.CurrentGun ~= LoadOut.melee.Name then
            EquipGunViewModel(ViewModel, LoadOut.melee.Name, Player, self.CurrentGun, "Melee")
            self.CurrentGun = LoadOut.melee.Name
            self.gunConfig = require(ViewModel[LoadOut.melee.Name].Config)
        elseif input.KeyCode == Enum.KeyCode.R then
            if self.CurrentAmmo ~= self.gunConfig.MaxAmmo then
                self.isReloading = true
                ViewModel.Humanoid:LoadAnimation(ReplicatedStorage.Animations.ViewModel.Reload.M416):Play()
                ReloadGunCharacter:FireServer(self.CurrentGun)

                task.delay(self.gunConfig.ReloadDelay, function()
                    self.gunConfig.magAmmo = self.gunConfig.maxAmmo
                    GunGUI.Mag.Text = self.gunConfig.maxAmmo
                    self.isReloading = false
                end)
            end
        end

        if input.KeyCode == Enum.KeyCode.Q then
            if not self.isLeaning then
                self.leaningSide = "Left"
                self.isLeaning = true
            else
                self.isLeaning = false
            end
        elseif input.KeyCode == Enum.KeyCode.E then
            if not self.isLeaning then
                self.leaningSide = "Right"
                self.isLeaning = true
            else
                self.isLeaning = false
            end
        end
    end
end

function InputHandler:handleInputEnded(input: InputObject, gameProcessedEvent: boolean)
    if gameProcessedEvent == false then
        if input.UserInputType == Enum.UserInputType.MouseButton1 then
            self.isHoldingMouseButton1 = false
        elseif input.UserInputType == Enum.UserInputType.MouseButton2 then
            self.isAiming = false
        end
    end
end

-- Interface for GameState
local GameState = {}
GameState.__index = GameState

function GameState.new()
    local self = setmetatable({}, GameState)
    self.RecoilSpring = SpringModule.new()
    self.BobbingSpring = SpringModule.new()
    self.SwayingSpring = SpringModule.new()
    self.updatedRecoilSpring = CFrame.new()
    self.updatedBobbingSpring = CFrame.new()
    self.updatedSwaySpring = CFrame.new()
    return self
end

function GameState:update(deltaTime: number)
    self.updatedRecoilSpring = self.RecoilSpring:update(deltaTime)
    self.updatedBobbingSpring = self.BobbingSpring:update(deltaTime)
    self.updatedSwaySpring = self.SwayingSpring:update(deltaTime)
end

-- Caching
local cachedBobbing = {}
local cachedSwaying = {}
local cachedLeaning = {}

local function getBobbing(addition: number): number
    if not cachedBobbing[addition] then
        cachedBobbing[addition] = math.sin(tick() * addition * 1.3) * .5
    end
    return cachedBobbing[addition]
end

local function getSwaying(mouseDelta: Vector2): Vector3
    local key = mouseDelta.X .. "_" .. mouseDelta.Y
    if not cachedSwaying[key] then
        cachedSwaying[key] = Vector3.new(-mouseDelta.X / 500, mouseDelta.Y / 200, 0)
    end
    return cachedSwaying[key]
end

local function getLeaning(leaningSide: string): number
    if not cachedLeaning[leaningSide] then
        local leanAngle = leaningSide == "Left" and math.rad(-45) or math.rad(45)
        cachedLeaning[leaningSide] = leanAngle
    end
    return cachedLeaning[leaningSide]
end

-- Main Game Loop
local inputHandler = InputHandler.new()
local gameState = GameState.new()

UserInputService.InputBegan:Connect(function(input, gameProcessedEvent)
    inputHandler:handleInputBegan(input, gameProcessedEvent)
end)

UserInputService.InputEnded:Connect(function(input, gameProcessedEvent)
    inputHandler:handleInputEnded(input, gameProcessedEvent)
end)

RunService.RenderStepped:Connect(function(deltaTime: number)
    gameState:update(deltaTime)

    local Bobbing = Vector3.new(getBobbing(10), getBobbing(5), getBobbing(5))
    local Character = Player.Character or Player.CharacterAdded:Wait()
    local MouseDelta = UserInputService:GetMouseDelta()

    gameState.BobbingSpring:shove(Bobbing / 20 * (Character.HumanoidRootPart.Velocity.Magnitude) / 20)
    gameState.SwayingSpring:shove(getSwaying(MouseDelta))

    ViewModel.FakeCamera.CFrame = game.Workspace.Camera.CFrame:ToWorldSpace(CFrame.new(gameState.updatedBobbingSpring.Y, gameState.updatedBobbingSpring.X, 0)) * CFrame.Angles(math.rad(gameState.updatedRecoilSpring.X)*4, 0, 0)
    Camera.CFrame = Camera.CFrame * CFrame.Angles(math.rad(gameState.updatedRecoilSpring.X), math.rad(gameState.updatedRecoilSpring.Y), math.rad(gameState.updatedRecoilSpring.Z))
    ViewModel.FakeCamera.CFrame *= CFrame.new(gameState.updatedSwaySpring.X, gameState.updatedSwaySpring.Y, 0)

    -- Leaning Logic
    if inputHandler.isLeaning then
        local leanAngle = getLeaning(inputHandler.leaningSide)
        ViewModel.FakeCamera.CFrame = ViewModel.FakeCamera.CFrame:Lerp(ViewModel.FakeCamera.CFrame * CFrame.Angles(0, 0, leanAngle), 0.1)
        Camera.CFrame = Camera.CFrame:Lerp(Camera.CFrame * CFrame.Angles(0, 0, leanAngle), 0.1)
    end

    -- Aiming Logic
    if inputHandler.isAiming then
        ViewModel.FakeCamera.Position = ViewModel.FakeCamera.Position:Lerp(ViewModel[inputHandler.CurrentGun].AimPart.Position, 0.2)
    else
        ViewModel.FakeCamera.Position = ViewModel.FakeCamera.Position:Lerp(ViewModel.HumanoidRootPart.Position, 0.1)
    end
end)

RunService.Heartbeat:Connect(function(deltaTime: number)
    GunGUI.Mag.Text = inputHandler.gunConfig.magAmmo
    if inputHandler.isHoldingMouseButton1 then 
        if inputHandler.canFire and inputHandler.gunConfig.magAmmo ~= 0 and inputHandler.gunConfig.magAmmo > 0 and not inputHandler.isReloading then
            if inputHandler.gunConfig.fireMode == "Semi" then
                inputHandler.isHoldingMouseButton1 = false
            end

            inputHandler.canFire = false
            gameState.RecoilSpring:shove(Vector3.new(inputHandler.gunConfig.UpRecoils[1], math.random(inputHandler.gunConfig.LeftRightRecoils[1], inputHandler.gunConfig.LeftRightRecoils[2])), inputHandler.gunConfig.RecoilShake)
            task.defer(function()
                task.delay(0.2, function()
                    gameState.RecoilSpring:shove(Vector3.new(inputHandler.gunConfig.UpRecoils[2], math.random(inputHandler.gunConfig.WrapLeftRightRecoils[1], inputHandler.gunConfig.WrapLeftRightRecoils[2]), -inputHandler.gunConfig.RecoilShake))
                end)
            end)

            task.spawn(function()
                inputHandler.gunConfig.fireSound:Play()
                for i,v in pairs(ViewModel[inputHandler.CurrentGun].Barrel:GetChildren()) do
                    if v:IsA("ParticleEmitter") then
                        v:Emit()
                    elseif v:IsA("PointLight") then
                        v.Enabled = true
                        task.delay(0.1, function()
                            v.Enabled = false
                        end)
                    end
                end
            end)

            local CastParams = RaycastParams.new()
            CastParams.IgnoreWater = true
            CastParams.FilterDescendantsInstances = {ViewModel, game.Players.LocalPlayer.Character}
            local Mouse = BulletModule.getEndPos(1000, CastParams)
            BulletModule.bullet(Player, ViewModel[inputHandler.CurrentGun].Barrel.Position, Mouse, inputHandler.gunConfig, true)
            BulletHandle:FireServer(ViewModel[inputHandler.CurrentGun].Barrel.Position, Mouse, inputHandler.gunConfig, inputHandler.CurrentGun)

            inputHandler.gunConfig.magAmmo -= 1
            task.delay(inputHandler.gunConfig.fireDelay, function()
                inputHandler.canFire = true
            end)
        end    
    end
end)

No I dont ? It doesnt even go directly 45 degree. Also tween glitches because of the bobbing and swaying so it doesnt work

Bro no way you recreated the script :sob:.

if inputHandler.isLeaning then
    local leanAngle = getLeaning(inputHandler.leaningSide)
    ViewModel.FakeCamera.CFrame = ViewModel.FakeCamera.CFrame:Lerp(ViewModel.FakeCamera.CFrame * CFrame.Angles(0, 0, leanAngle), 0.1)
    Camera.CFrame = Camera.CFrame:Lerp(Camera.CFrame * CFrame.Angles(0, 0, leanAngle), 0.1)
end

also this part just doesnt work rn I have another issue I fixed it but now it doesnt go back smoothly. Like it just goes back directly in to 0 degrees. New Script:


	if isLeaning == true then
		local alpha = math.clamp(pastTime/0.3, 0, 1)
		pastTime += deltaTime
		if leaningSide == "Right" then
			ViewModel.FakeCamera.CFrame = ViewModel.FakeCamera.CFrame:Lerp(ViewModel.FakeCamera.CFrame * CFrame.Angles(0, 0, math.rad(-45)), alpha)
			Camera.CFrame = Camera.CFrame:Lerp(ViewModel.FakeCamera.CFrame, alpha)
		elseif leaningSide == "Left" then

			--print(alpha)
			ViewModel.FakeCamera.CFrame = ViewModel.FakeCamera.CFrame:Lerp(ViewModel.FakeCamera.CFrame * CFrame.Angles(0, 0, math.rad(45)), alpha)
			Camera.CFrame = Camera.CFrame:Lerp(ViewModel.FakeCamera.CFrame, alpha)
			print(alpha)
		end
	else
		local alpha = math.clamp(pastTime/0.3, 0, 1)

		pastTime += deltaTime
		if leaningSide == "Right" then
			ViewModel.FakeCamera.CFrame = ViewModel.FakeCamera.CFrame:Lerp(ViewModel.FakeCamera.CFrame * CFrame.new(0, 0, math.rad(0)), alpha)
			Camera.CFrame = Camera.CFrame:Lerp(ViewModel.FakeCamera.CFrame, alpha)
		elseif leaningSide == "Left" then
			ViewModel.FakeCamera.CFrame = ViewModel.FakeCamera.CFrame:Lerp(ViewModel.FakeCamera.CFrame * CFrame.Angles(0, 0, 0), alpha)
			Camera.CFrame = Camera.CFrame:Lerp(ViewModel.FakeCamera.CFrame, alpha)
			print(alpha)
		end
		if alpha >= 1 then -- this part is for stopping the lerp
			pastTime = 0
			leaningSide = ""
		end
	end

and it doesnt do sway or Bobbing while leaning

I couldn’t test because I’m on my phone :skull:

youre setting the camera.CFrame to a direct CFrame

unless youre constantly changing the camera based off of the fakecamera, you are definitely setting the CFrame directly

Yeah but it works because Im setting it by 0.1 0.2 0.3 0.4 0.5 0.6 … But it doesnt go back like this :joy: