Wall run system, camera Rotation not working as expected

I have a wall run system and when you start the wall run I want to rotate the camera smoothly based on the direction your going in and when your done it goes back to normal smoothly too, I have the code done but not working as expected.

I tried lerping but it still behaves as if im not lerping and just setting the camera’s new cframe, also NOTE: most of this code was to clamp the cameras rotation, but I probably dont need that anymore.

CFrame.Angles(0, 0, math.rad(lookDir * cameraRotation))

also this ^^^ is the camera’s cframe angle code, lookDir is either 1 or -1 depending on the direction the player is looking and cameraRotation is some number picked by me

-- // Camera Rotation
local currentRot = camera.CFrame * CFrame.Angles(0, 0, math.rad(lookDir * cameraRotation))
local rx, ry, rz = currentRot:ToOrientation()
local rotClamp = math.clamp(math.deg(rz), -cameraRotation, cameraRotation)
local newCFrame = CFrame.new(camera.CFrame.Position) * CFrame.fromOrientation(rx, ry, math.rad(rotClamp))
camera.CFrame = camera.CFrame:Lerp(newCFrame, 0.1)


as you see it just snaps the rotation instead of smoothing it

1 Like

I’m not sure how well :Lerp() works for CFrames since I have only used them for color animations in certain situations. But what I would do is use TweenService to create a smooth animation from your starting CFrame to your ending CFrame. TweenService can make almost any property for almost any instance change smoothly. That’s why TweenService is my fav. Anways, done with the tangeants, try using TweenService:Create() instead of :Lerp()!

Tween Service almost works but I think since its running in Run Service, it has a hard time running so it only runs after I stop wall running.

also here’s the code that I used

tweenService:Create(camera, TweenInfo.new(0.5), {CFrame = newCFrame}):Play()

Try creating the tween first then playing it later.
If that doesn’t work you could try doing this:

while rotating == true do
   camera.CFrame = camera.CFrame:Lerp(newCFrame, 0.01)
   task.wait(0.01)
   if camera.CFrame == camera.CFrame:Lerp(newCFrame, 0.1) then
      rotating =  false
   end
end

I tried that and the same problems occurs + another weird camera bug

also that code you made isn’t gonna work

Yeah, I can’t figure out how CFrame:Lerp() works. But well, good luck on solving your problem! And if you can’t figure it out after a long time, take a break. After the break, you may just solve the problem in a few short minutes! (it really works!)

Is your camera a custom camera? If not, you need to do some work or remove the Lerp.

nope its just the default roblox camera

Yeah, the camera resets itself so you’d need to either create a custom camera or do some sort of hacky CFrame method (which I’m not experienced in).

alright Ill try a custom camera real quick

It won’t work out of the box, you need to make the CFrame.lookAt part’s up vector lerped to your wall’s normal.

what are you talking about? 30 ch

The part normal or the CFrame.lookAt?

yeah the CFrame.lookAt() how are you saying to use it?

The documentation says how to use it:
CFrame.lookAt | Roblox Creator Documentation

yeah I know how to use it but, I’m saying how are you saying to use it to fix my problem?

If this is within a RunService update loop, just lerp by a factor of deltaTime.
You can find more info about it here, but in short, it’s the amount of elapsed time since the previous frame of whatever update you’re using.

It also is the first argument passed for every RunService update loop, other than Stepped where it is the second argument passed.

Here’s an example of how I’d use it in your case

local RunService = game:GetService("RunService")

-- The higher this value is, the faster the camera rotation should tween.
local SpeedMultiplier = 10

-- Use whatever update loop you're currently using (probably render stepped?)
RunService.RenderStepped:Connect(function(deltaTime: number)

  local currentRot = camera.CFrame * CFrame.Angles(0, 0, math.rad(lookDir * cameraRotation))
  local rx, ry, rz = currentRot:ToOrientation()
  local rotClamp = math.clamp(math.deg(rz), -cameraRotation, cameraRotation)
  local newCFrame = CFrame.new(camera.CFrame.Position) * CFrame.fromOrientation(rx, ry, math.rad(rotClamp))
  camera.CFrame = camera.CFrame:Lerp(newCFrame, SpeedMultiplier * deltaTime)

end)

ty but I tried this and its still snapping

Have you tried lowering the SpeedMultiplier variable I gave you?
If that still doesn’t work, can you try sending the entire update loop for the camera instead of just a small snippet?

yeah lowering it just lowers the rotation angle

heres the code,

local rotationSpeed = 5
local cameraRotation = 45

runService.RenderStepped:Connect(function(deltaTime)

	-- // Calculate Wall Directions
	local wallNormal = result.Normal
	local wallFowardDir = wallNormal:Cross(Vector3.new(0, 1, 0))
	local dot = root.CFrame.LookVector:Dot(wallFowardDir)
	local lookDir = dot < 0 and -wallFowardDir.Magnitude or wallFowardDir.Magnitude
			
	-- // Camera Rotation
	local currentRot = camera.CFrame * CFrame.Angles(0, 0, math.rad(lookDir * cameraRotation))
	local rx, ry, rz = currentRot:ToOrientation()
	local rotClamp = math.clamp(math.deg(rz), -cameraRotation, cameraRotation)
	local newCFrame = CFrame.new(camera.CFrame.Position) * CFrame.fromOrientation(rx, ry, math.rad(rotClamp))
	camera.CFrame = camera.CFrame:Lerp(newCFrame, rotationSpeed * deltaTime)

end)