How to create a nice bobbing motion!

Hello everyone. I’ve come back with another tutorial. This time I would like to help anyone trying to create some sort of bobbing system that feels realistic.

Pre-required knowledge (Helpful to understand)

  • Trig
  • Knowledge of Sine and Cosine Wave Graphing.
  • Amplitude, Frequency, and the general form of a Sinusoidal Wave

Quick Rundown

  • As everyone understands, Sine and Cosine waves start at specific values.

  • 0 is the value that Sine waves begin on. (Altered via amplitude/vertical shift)

  • 1 is the value that Cosine waves will begin on. (Altered via amplitude/vertical shift)

  • Both Cos and Sin have ranges between [-1, 1], this can be altered via Amplitude

  • Both Cos and Sin have domains between [-inf, inf] meaning they repeat ultimately.

  • Both Cos and Sin have a period of 2 PI which can be altered via Frequency(2 PI * Frequency = Period)

Introducing the Figure 8 Pattern

A figure 8 pattern can be described by a simple formula.
Recent
This formula will stay true even if both Trigonometric functions are the same, but the base formula showed above seems to replicate it the closest from my knowledge.

You can essentially think of Frequency as how many times the wave peaks/rotates on the unit circle. So if we peak/rotate a complete 360(2 PI) on the Sin wave 2 times and then on the Cos wave once we then get a sort of Figure 8 Pattern going.

Desmos Raw Visual of Figure 8
Desmos Explanation of Figure 8 ← Recommended

Sadly I will not add any code examples for this! I do not want people to piggy back off these tutorials, I’d rather have you learn more(I added a small example, but learn from this code! It’s not easy to read…)

If you want an explanation of the Unit circle and Trigonometric functions please request for it in the comments.

Example Usage

--// This is located in StarterCharacterScripts
local RS = game:GetService("RunService")

local Character = script.Parent
local Humanoid = Character:WaitForChild("Humanoid")

local function RetrieveFigure8(t, frequency_factor, amplitude_factor)
	frequency_factor, amplitude_factor = frequency_factor or 1, amplitude_factor or 1
	return Vector2.new(
		math.cos(frequency_factor*t) * amplitude_factor,
		math.sin((2*frequency_factor)*t) * amplitude_factor
	)
end


RS.RenderStepped:Connect(function()
	local Position = RetrieveFigure8(os.clock(), 5, 0.1)
	local isMoving = Humanoid.MoveDirection.Magnitude > 0
	local Offset = isMoving and Vector3.new(Position.X, Position.Y, 0) or Vector3.zero
	Humanoid.CameraOffset = Humanoid.CameraOffset:Lerp(Offset, 0.5)
end)

General Applications of this

  • Weapon/Item Bobbing
  • Camera Bobbing
  • Angular Bobbing on Camera or Weapon/Item
19 Likes