Frame Interpolation

Godot Version

4.3.1

Question

Hi everyone,

I’m making a interpolator for my multiplayer code. The basic idea is I receive an object’s position, and move it from its old position to the new one before the next position arrives. I’m currently experimenting with the interpolation part using two sprites, a physics bound one and one that follows each frame, and came up with this:

@onready var cursor = $"Sprite2D"
@onready var follower = $"Sprite2D2"
var visual_object = null
var physics_object = null
var linear_direction = null
var frame_distance_percent = 0

func _process(delta: float) -> void:
	# Get percentage of frame this delta takes up in terms of physics rate
	var frame_percent = 1.0/((1.0/delta)/60.0)
	# Add to variable to keep track of time until next frame
	frame_distance_percent = frame_percent + frame_distance_percent
	# If we haven't reached the end of the current frame, interpolate position
	if frame_distance_percent <= 1.0:
		# Move along direction from visual object position to physics object position, with percentage
		# equal to the time within the current frame
		var interp_pos = visual_object + linear_direction * frame_distance_percent
		follower.global_position = interp_pos

func _physics_process(delta: float) -> void:
	var pos = get_viewport().get_mouse_position()
	# Set current position data of both objects
	# As well as reset the frame percentage
	cursor.global_position = pos
	physics_object = pos
	visual_object = follower.global_position
	linear_direction = physics_object-visual_object
	frame_distance_percent = 0

I tried using lerp to do this instead but had some trouble since it would smooth out the movement instead of making even, snappy jumps (if that makes any sense).

The way I’m currently doing this smoothing is I take the two positions, split the direction vector of them into equal segments, and move the following sprite each process call an equal distance calculated by delta. I was wondering if anyone had any tips to improve my method above, since I feel like doing this a few times every frame for multiple objects would be quite expensive…

On a side note, I was planning on doing the same thing to smooth out my player camera. Basically the character body would move in physics time, while the camera would be interpolated to the body to give the illusion of smoother movement while running/walking. Is this a good idea or does setting the camera position this many times reduce fps?

Thanks

try tween? but even with tween it’s still using inner process frame (or physics frame, depending what you set it), so you will never escape for having each node to do _proccess and _physics_process. these functions are called for every nodes, just dont do any heavy calculation for each frame, that’s how you minimize the processing calculation

‘Never escape’ is too much i think, can trigger to stop the _process or _physics_process of a node by set_physics_process, set_process, and set_physics_process_internal
but by default any node will have the _process and _physics_process running

1 Like

For multiplayer code, you’ll usually want more than 1 frame of to interpolate between. For example, Valve games use 0.1 seconds which is about 7 ticks. This is because if packets are dropped, there is still data to be interpolated between.

Here is the basic idea with 1 frame of interpolation, but again you’ll want about 7 snapshots to work with. You can store these 7 snapshots in a ring buffer, and then find which is closest in time to the render_time.

static var interp_period_usec: int = 16666

func interp() -> void:
	var current_time: int = Time.get_ticks_usec()
	var render_time: int = current_time - interp_period_usec

	var T: float = remap(render_time, snapshot_now.tick, snapshot_previous.tick, 0.0, 1.0)
	T = clampf(T, 0.0, 1.0)

	var interp_pos: Vector3 = snapshot_now.position.lerp(snapshot_previous.position, T)

For further reading, I recommend Glenn Fiedler’s 2015 talk, “Physics for Game Programmers”. Specifically the section on snapshot interpolation. Additionally Gabriel Gambetta’s “Fast-Paced Multiplayer: Client-Server Game Architecture”. Best of luck to you.