Need help converting 3.5 "ViewBob" Sine wave code to 4.2

Godot Version



Recently I’ve been converting my game project to the newest available Godot version-- It’s been going smoothly enough, but I’ve been stumped on the following for a while;
I have a script attached to a Camera3D node that uses two sine waves for X and Y interpolation of the camera to create a smooth “View bobbing” effect-- the effect works fine in-game while moving on some axis’, but breaks on others and breaks the intended effect.

I had implemented a fix prior in Godot 3.5 but the fix now no-longer works, I was wondering if there was a way to make these sine waves relative to the camera position in Godot 4 (I’m sure there is, I’m just not certain of what the solution is)

I have a gif attached below to hopefully visually explain what I’m talking about since I’m not the best at describing, I’ve amplified the bob effect to help showcase the issue

The code for the ViewBob script is below too if needed

extends Camera3D

var bobAmp: float = 0.15
var Speed2D: float = 16.0
var bobTime: float = 1.0
var Player: CharacterBody3D
var originalOffset: Vector3
var returnTimer: float = 0
var returnDuration: float = 1.5

func _ready():
	Player = $"../.."
	originalOffset = global_transform.origin - Player.global_transform.origin

func calculateBobOffset(t: float) -> float:
	return sin(t) * bobAmp

func _on_pawn_moving():
	var Offset = Vector3.ZERO
	var finalOffset = Offset + originalOffset
	if not Player.is_on_floor():

	bobTime += get_process_delta_time() * Speed2D
	Offset.y = calculateBobOffset(bobTime * 2.0)
	Offset.x = calculateBobOffset(bobTime)

	# Adjust the camera's bob position based on its rotation
	Offset = global_transform.basis * Offset
	global_transform.origin = Player.global_transform.origin + finalOffset

func _on_pawn_stopped():
		returnTimer += get_process_delta_time()
		var t = returnTimer / returnDuration
		global_transform.origin = lerp(global_transform.origin, Player.global_transform.origin + originalOffset, t)

Any help, tips or criticism would be appreciated! Godot 4 changes a lot and it’s been a lot of growing pains

Returntimer is never reset. Your lerp will only work once.

This is bad practice to reference a parent node from a child. Honestly I’m surprised if this is working, since this ready function will be called before player is ready.

Another thing I would say is that you don’t need the player at all, and you don’t need to work in global space to do this. If you do it all local you don’t need the basis transform either. When you setup your player scene with a child camera your originalOffset will just be the starting position of the camera.

Watching your clip it isn’t obvious what the problem is. Anyway that’s my input.