So you've been working on a multiplayer game and it's great, but now you try it with a friend and it's terribly laggy. You see, networking isn't about pushing data over a socket, that's the easy part - the real issue is latency and unreliability. When you're making a multiplayer game, you should make latency and unreliability part of your game from the begining or you'll have a lot headaches later on.

Here's how you can do it in Godot but the technique is going to be the same for Unity and any other engine. Download the full project or simply copy the code below.

Download   SimulateNetwork.zip

Server.gd
var net_fps = 10
var net_fps_timer = 0.0

func _physics_process(delta):
	var t = OS.get_ticks_msec() / 1000.0
	var pos = Vector3(sin(t), cos(t), 0.0) * 5.0
	translation = pos
	
	net_fps_timer += delta
	if net_fps_timer < 1.0/net_fps:
		return
	net_fps_timer -= 1.0/net_fps
	netcode.toClient.send(pos)
Client.gd
func _physics_process(delta):
	var pos = netcode.toClient.recv()
	if pos == null:
		return
	translation = pos
netcode.gd
class UDPMessageQueue:
	var min_latency = 0.100
	var max_latency = 0.300
	var drop_rate = 0.10
	var dup_rate = 0.05
	var queue = []
	
	func _init():
		randomize()
	
	func send(msg):
		if randf() < drop_rate:
			return
		var t = OS.get_ticks_msec() / 1000.0
		var t2 = t + min_latency + randf()*(max_latency-min_latency)
		queue.push_back([t2, msg])
		while randf() < dup_rate:
			var t3 = t + min_latency + randf()*(max_latency-min_latency)
			queue.push_back([t3, msg])
		queue.sort_custom(self, "sorti")
	
	func sorti(a, b):
		return a[0] < b[0]
	
	func recv():
		if queue.empty():
			return null
		var t = OS.get_ticks_msec() / 1000.0
		if t < queue[0][0]:
			return null
		return queue.pop_front()[1]

var toClient = UDPMessageQueue.new()

Watch the Video