Camera Bobbing Changes Character Orientation

Hello, for a little-bit now, I’ve been stumped on a problem where a first person camera bob would cause my character to turn relative to the bobbing. Fixes I know about is using the Humanoid’s CameraOffsetproperty to manipulate the camera, but this severely limits the extent I can manipulate the view-bobbing. Another fix I do know about is disabling the Humanoid’s AutoRotate property and manually updating it but I do also want to avoid that if at all possible.

My main method of changing the camera’s viewbobbing is by changing the camera’s CFrame with a trig function:

local SwayX = SWAY_X_AMPLITUDE * math.cos(tick() * SWAY_X_FREQUENCY) local SwayY = SWAY_Y_AMPLITUDE * math.sin(tick() * SWAY_Y_FREQUENCY) + SWAY_Y_OFFSET Camera.CFrame = Camera.CFrame + Vector3.new(SwayX, SwayY, 0) 

Your camera bob is being interpreted as camera rotation, so the Humanoid turns to follow it. Apply the camera bob after the default camera runs and by translating the camera in it’s local space without changing rotation.

local RS = game:GetService("RunService") local cam = workspace.CurrentCamera local SWAY_X_AMPLITUDE, SWAY_X_FREQ = 0.15, 9 local SWAY_Y_AMPLITUDE, SWAY_Y_FREQ = 0.10, 13 local SWAY_Y_OFFSET = 0 local function onRenderStep(dt)	local base = cam.CFrame	local t = tick()	local swayX = SWAY_X_AMPLITUDE * math.cos(t * SWAY_X_FREQ)	local swayY = SWAY_Y_AMPLITUDE * math.sin(t * SWAY_Y_FREQ) + SWAY_Y_OFFSET	-- translate in camera-space (no new yaw/pitch/roll)	local worldOffset = base:VectorToWorldSpace(Vector3.new(swayX, swayY, 0))	local pos = base.Position + worldOffset	-- preserve look vector + up vector exactly	cam.CFrame = CFrame.lookAt(pos, pos + base.LookVector, base.UpVector) end -- run after Roblox camera finishes (prevents feedback into character facing) RS:BindToRenderStep("ViewBob", Enum.RenderPriority.Camera.Value + 1, onRenderStep) 
2 Likes

The line Enum.RenderPriority.Camera.Value + 1 doesn’t really fix the issue, I’ve already had this in my code. Secondly, one issue was with me offsetting the X value, that seemed to cause the issue for some reason.
Also this code still has the same issue, but thanks for the reply!

1 Like

Anim10

I managed to replicate this functionality using this LocalScript in StarterPlayer > StarterPlayerScripts (for R15):

local RS = game:GetService("RunService") local cam = workspace.CurrentCamera local SWAY_X_AMPLITUDE, SWAY_X_FREQ = 0.08, 9 local SWAY_Y_AMPLITUDE, SWAY_Y_FREQ = 0.12, 13 local SWAY_Y_OFFSET = 0 local cachedPos, Xv, Yv, Zv RS:BindToRenderStep("VB_Cache", Enum.RenderPriority.Camera.Value, function()	local base = cam.CFrame	cachedPos = base.Position	Xv, Yv, Zv = base.XVector, base.YVector, base.ZVector end) RS:BindToRenderStep("VB_Apply", Enum.RenderPriority.Camera.Value + 2, function(dt)	if not cachedPos then return end	local t = tick()	local swayX = SWAY_X_AMPLITUDE * math.cos(t * SWAY_X_FREQ)	local swayY = SWAY_Y_AMPLITUDE * math.sin(t * SWAY_Y_FREQ) + SWAY_Y_OFFSET	local pos = cachedPos + (Xv * swayX) + (Yv * swayY)	cam.CFrame = CFrame.fromMatrix(pos, Xv, Yv, Zv) end) -- (When disabling): RS:UnbindFromRenderStep("VB_Cache"); RS:UnbindFromRenderStep("VB_Apply") 

Use this for R6:

local RS = game:GetService("RunService") local cam = workspace.CurrentCamera local SWAY_X_AMPLITUDE, SWAY_X_FREQ = 0.08, 9 local SWAY_Y_AMPLITUDE, SWAY_Y_FREQ = 0.12, 13 local SWAY_Y_OFFSET = 0 local cachedPos, Xv, Yv, Zv RS:BindToRenderStep("VB_Cache", Enum.RenderPriority.Camera.Value + 1, function()	local base = cam.CFrame	cachedPos = base.Position	Xv, Yv, Zv = base.XVector, base.YVector, base.ZVector end) RS:BindToRenderStep("VB_Apply", Enum.RenderPriority.Camera.Value + 2, function(dt)	if not cachedPos then return end	local t = tick()	local swayX = SWAY_X_AMPLITUDE * math.cos(t * SWAY_X_FREQ)	local swayY = SWAY_Y_AMPLITUDE * math.sin(t * SWAY_Y_FREQ) + SWAY_Y_OFFSET	local pos = cachedPos + (Xv * swayX) + (Yv * swayY)	cam.CFrame = CFrame.fromMatrix(pos, Xv, Yv, Zv) end) 
2 Likes

Not exactly a solution, but thought it was fun lol

1 Like