Help with Head-Bobbing Script

Hi everyone, I am trying to incorporate a head-bobbing script into a game of mine, but it isn’t working. I haven’t found any head-bobbing script that worked as intended.

I am using the following script, all credit is to BuiltToWreck and his Devforum tutorial “Configurable Head Bobbing Script”. I did put it in a local script under Starter Character Scripts, and I tried locking in first person though that didn’t work. I’m not asking in a comment under his tutorial because every head-bobbing script hasn’t worked for me, so I figure there’s something wrong with my implementation.

image

--[[
Created by @BuiltToWreck

Attribution-ShareAlike 4.0 International (CC BY-SA 4.0)
https://creativecommons.org/licenses/by-sa/4.0/

You are free to:
- Share — copy and redistribute the material in any medium or format
- Adapt — remix, transform, and build upon the material
  for any purpose, even commercially. 

Under the following terms:
- Attribution — You must give appropriate credit, provide a link to the license, 
  and indicate if changes were made. You may do so in any reasonable manner, but 
  not in any way that suggests the licensor endorses you or your use.
- ShareAlike — If you remix, transform, or build upon the material, you must
  your contributions under the same license as the original.
- No additional restrictions — You may not apply legal terms or technological 
  measures that legally restrict others from doing anything the license permits.

Place in StarterCharacterScripts
Adjust constants to your liking.

]]

-- CONSTANTS --
-- Camera position offset from HumanoidRootPart:
local OFFSET = Vector3.new(0, 3, 0)
-- Mouse sensitivity multiplier
local SENSITIVITY = 0.006
-- Verticle angle limits (how far you can look up and down):
local UPPER_ANGLE_LIMIT = math.rad(85)
local LOWER_ANGLE_LIMIT = math.rad(-85)
-- How many bobs per second horizontally and vertically:
local BOB_FREQUENCY_Y = 4
local BOB_FREQUENCY_X = 2
-- How intense the horizontal and vertical bobs are:
local BOB_AMPLITUDE_X = 0.6
local BOB_AMPLITUDE_Y = 0.4
-- The maximum velocity that affects the intensity of the bob:
local MAX_VELOCITY = 16
-- How fast it takes for bobbing to start/stop when you start/stop moving:
local RECENTER_SPEED = 4

-- SERVICES --
local RunService = game:GetService("RunService")
local Players = game:GetService("Players")
local UserInputService = game:GetService("UserInputService")

-- REFERENCES --
local localPlayer = Players.LocalPlayer
local character = localPlayer.Character or localPlayer.CharacterAdded:Wait()
local currentCamera = workspace.CurrentCamera

-- VARIABLES --
local cameraAngle = Vector2.new(0, 0)
local currentTime = 0
local velocityMultiplier = 0

-- FUNCTIONS --
local function scalarLerp(a, b, c)
	c = math.clamp(c, 0, 1)
	return a + c *	(b - a)
end

local function renderStepped(deltaTime)
	local humanoidRootPart = character:FindFirstChild("HumanoidRootPart")
	local mouseDelta = UserInputService:GetMouseDelta() * SENSITIVITY
	
	-- Calculate bob offsets
	currentTime += deltaTime
	local bobOffsetY = (math.sin(currentTime * math.pi * BOB_FREQUENCY_Y) - 0.5) * BOB_AMPLITUDE_Y
	local bobOffsetX = (math.sin(currentTime * math.pi * BOB_FREQUENCY_X) - 0.5) * BOB_AMPLITUDE_X
	
	-- Smooth between bobbing and neutral based on horizontal velocity
	local velocityMagnitude = (humanoidRootPart.Velocity * Vector3.new(1,0,1)).Magnitude
	local targetVelocityMultiplier = math.clamp(velocityMagnitude, 0, MAX_VELOCITY) / MAX_VELOCITY
	velocityMultiplier = scalarLerp(velocityMultiplier, targetVelocityMultiplier, RECENTER_SPEED * deltaTime)
	bobOffsetX *= velocityMultiplier
	bobOffsetY *= velocityMultiplier
	
	-- Update the camera angle, clamp it to angle limits
	cameraAngle -= mouseDelta
	cameraAngle = Vector2.new(
		cameraAngle.X, 
		math.clamp(cameraAngle.Y, LOWER_ANGLE_LIMIT, UPPER_ANGLE_LIMIT)
	) 
	
	-- Set the cframe of the camera
	currentCamera.CFrame = 
		CFrame.new(humanoidRootPart.Position + OFFSET + Vector3.new(0, bobOffsetY, 0)) * 
		CFrame.Angles(0, cameraAngle.X, 0) * 
		CFrame.Angles(cameraAngle.Y, 0, 0) *
		CFrame.new(bobOffsetX, 0, 0)
end

-- LOGIC/SETUP/CONNECTIONS --
localPlayer.CharacterAppearanceLoaded:Wait()
currentCamera.CameraType = Enum.CameraType.Scriptable
UserInputService.MouseBehavior = Enum.MouseBehavior.LockCenter

-- Make character invisible
for _, desc in ipairs(character:GetDescendants()) do
	if desc:IsA("Part") then
		desc.Transparency = 1
	end
end

RunService.RenderStepped:Connect(renderStepped)
1 Like

hi mate here is what i use for my horror games both are local scripts :+1:

first the first person script in startgui

local forceFirstPerson = true

local fieldOfView = 70

local cameraOffset = Vector3.new(0,0,0)

local accessoriesVisible = false

local player = game.Players.LocalPlayer

local character = player.Character or player.CharacterAdded:wait()

local human = character:WaitForChild(“Humanoid”)

local camera = game.Workspace.CurrentCamera

if forceFirstPerson then player.CameraMode = Enum.CameraMode.LockFirstPerson end

camera.FieldOfView = fieldOfView

human.CameraOffset = cameraOffset

local function lock(part)

if part and part:IsA(“BasePart”) and part.Name ~= “HumanoidRootPart” and part.Name ~= “Head” and (accessoriesVisible or (not accessoriesVisible and not part.Parent:IsA(“Accessory”))) then

part.LocalTransparencyModifier = part.Transparency

part.Changed:connect(function (property)

part.LocalTransparencyModifier = part.Transparency

end)

end

end

for _,v in pairs(character:GetDescendants()) do

lock(v)

end

character.DescendantAdded:connect(lock)

camera.Changed:Connect(function (property)

if property == “CameraSubject” then

if camera.CameraSubject and camera.CameraSubject:IsA(“VehicleSeat”) and human then

camera.CameraSubject = human;

end

end

end)

1 Like

and now the script in startercharecterscript:

local RunService = game:GetService(“RunService”)

local playerModel = script.Parent
local humanoid = playerModel:WaitForChild(“Humanoid”)

local function updateBobbleEffect()
local now = tick()
if humanoid.MoveDirection.Magnitude > 0 then – Are we walking?
local velocity = humanoid.RootPart.Velocity
local bobble_X = math.cos(now * 5) / 4
local bobble_Y = math.abs(math.sin(now * 5)) / 3

	local bobble = Vector3.new(bobble_X,bobble_Y,-1) * math.min(1, velocity.Magnitude / humanoid.WalkSpeed)
	humanoid.CameraOffset = humanoid.CameraOffset:lerp(bobble,0.25)
else
	-- Scale down the CameraOffset so that it shifts back to its regular position.
	humanoid.CameraOffset = Vector3.new(0,0,-1)
end

end

– Update the effect on every single frame.
RunService.RenderStepped:Connect(updateBobbleEffect)

This is made for an r6 rig though not sure what you are using :+1:

can i use it for my game? do i need to credit to u

all good mate use it as you like i got it from someone else from memory no need to credit me
:v:

1 Like