Godot 3 Tutorial– Networking

This video covers networking in the Godot game engine.  First, we start off creating a simple UDP socket server and a client.  We then illustrate the use of HTTPClient to make a REST web service request.  We then create a simple ENet based client and server in Godot.  Finally, we create a simple lobby and networked game using GDScript keywords master, slave, sync, and remote.

The Video

Code Samples

SimpleClient.gd

extends SceneTree

func _init():
  var socket = PacketPeerUDP.new()
  
  socket.set_dest_address("127.0.0.1",4242)
  socket.put_packet("quit".to_ascii())
    
  print("Exiting application")    
  self.quit()

SimpleServer.gd

extends SceneTree

func _init():
  var done = false
  
  var socket = PacketPeerUDP.new()
  if(socket.listen(4242,"127.0.0.1") != OK):
    print("An error occurred listening on port 4242")
    done = true;
  else:
    print("Listening on port 4242 on localhost")

  while(done != true):
    if(socket.get_available_packet_count() > 0):
      var data = socket.get_packet().get_string_from_ascii()
      if(data == "quit"):
        done = true
      else:
        print("Data received: " + data)
  socket.close()        
  print("Exiting application")    
  self.quit()

HTTPRequest.gd

extends Button

func _ready():
  $HTTPRequest.connect("request_completed",self,"_on_HTTPRequest_request_completed")

func _on_Button_pressed():
  $HTTPRequest.request("https://jsonplaceholder.typicode.com/todos/1",PoolStringArray([]),false)

func _on_HTTPRequest_request_completed( result, response_code, headers, body ):
  if(response_code == 200):
    get_parent().get_node("Label").text = body.get_string_from_utf8()

Client.gd

extends Node2D

func _ready():
  var network = NetworkedMultiplayerENet.new()
  network.create_client("127.0.0.1", 4242)
  get_tree().set_network_peer(network)
  network.connect("connection_failed",self,"_on_connection_failed")
  get_tree().multiplayer.connect("network_peer_packet",self,"_on_packet_received")
  
func _on_connection_failed(error):
  $labelStatus.text = "Error connecting to server " + error

func _on_packet_received(id,packet):
  $labelServerData.text = packet.get_string_from_ascii()

func _on_buttonConnect_pressed():
  var network = NetworkedMultiplayerENet.new()
  network.create_client("127.0.0.1", 4242)
  get_tree().set_network_peer(network)

  func _on_buttonDisconnect_pressed():
    get_tree().set_network_peer(null)  

Server.gd

extends Label

func _ready():
  var network = NetworkedMultiplayerENet.new()
  network.create_server(4242, 2)
  get_tree().set_network_peer(network)
  
  network.connect("peer_connected",self,"_peer_connected")
  network.connect("peer_disconnected",self,"_peer_disconnected")
  
func _peer_connected(id):
  text = text + "\nUser " + str(id) + " connected"
  get_parent().get_node("labelUserCount").text = "Total Users:" + str(get_tree().get_network_connected_peers().size())
  
func _peer_disconnected(id):
  text = text + "\nUser " + str(id) + " disconnected"
  get_parent().get_node("labelUserCount").text = "Total Users:" + str(get_tree().get_network_connected_peers().size())
extends Button

func _on_buttonSendData_pressed():
  print("Sending data to client")
  var textToSend = get_parent().get_node("textToSend").text
  get_tree().multiplayer.send_bytes(textToSend.to_ascii())

Lobby.gd

extends Node2D

func _ready():
  get_tree().connect("network_peer_connected", self, "_player_connected")

func _player_connected(id):
  print("Player connected to server!")
  #Game on!
  globals.otherPlayerId = id
  var game = preload("res://Game.tscn").instance()
  get_tree().get_root().add_child(game)
  hide()

func _on_buttonHost_pressed():
  print("Hosting network")
  var host = NetworkedMultiplayerENet.new()
  var res = host.create_server(4242,2)
  if res != OK:
    print("Error creating server")
    return

  $buttonJoin.hide()
  $buttonHost.disabled = true
  get_tree().set_network_peer(host)


func _on_buttonJoin_pressed():
  print("Joining network")
  var host = NetworkedMultiplayerENet.new()
  host.create_client("127.0.0.1",4242)
  get_tree().set_network_peer(host)
  $buttonHost.hide()
  $buttonJoin.disabled = true

Game.gd

extends Node2D

func _ready():
  #First create ourself
  var thisPlayer = preload("res://Player.tscn").instance()
  thisPlayer.set_name(str(get_tree().get_network_unique_id()))
  thisPlayer.set_network_master(get_tree().get_network_unique_id())
  add_child(thisPlayer)
  
  #Now create the other player
  var otherPlayer = preload("res://Player.tscn").instance()
  otherPlayer.set_name(str(globals.otherPlayerId))
  otherPlayer.set_network_master(globals.otherPlayerId)
  add_child(otherPlayer)

Player.gd

extends Node2D

slave func setPosition(pos):
  position = pos
  
master func shutItDown():
  #Send a shutdown command to all connected clients, including this one
  rpc("shutDown")
  
sync func shutDown():
  get_tree().quit()
  
func _process(delta):
  var moveByX = 0
  var moveByY = 0
  if(is_network_master()):
    if Input.is_key_pressed(KEY_LEFT):
      moveByX = -5
  
    if Input.is_key_pressed(KEY_RIGHT):
      moveByX = 5

    if Input.is_key_pressed(KEY_UP):
      moveByY = -5

    if Input.is_key_pressed(KEY_DOWN):
      moveByY = 5

    if Input.is_key_pressed(KEY_Q):
      shutItDown()
      
    # Tell the other computer about our new position so it can update       
    rpc_unreliable("setPosition",Vector2(position.x - moveByX, position.y))   

  # Move our local player
  translate(Vector2(moveByX,moveByY))

Back to Tutorial Series Homepage

Scroll to Top