Cool! Is there unity frameworks or do you have to run python from unity or how do you do this?
banddans
Creator of
Recent community posts
Some code for WebRTC if you wanna learn:
Signaling server (js):
import WebSocket, { WebSocketServer } from "ws";
const wss = new WebSocketServer({ port: 9396 });
const messages = {
ASSIGN_ID: 0,
JOIN_LOBBY: 1,
PLAYERS_FOUND: 2,
SEND_ICE_CANDIDATE: 3,
SEND_DESCRIPTION: 4,
RECEIVE_ICE_CANDIDATE: 5,
RECEIVE_DESCRIPTION: 6,
};
let players = {};
let waiting_players = [];
let waiting_player_ids = [];
let next_player_id = 2;
const PLAYERS_IN_GAME = 3;
wss.on("connection", function connection(ws) {
const player_id = next_player_id;
players[player_id] = ws;
next_player_id += 1;
ws.on("close", function close() {
delete players[player_id];
console.log("Player left :(");
});
ws.on("error", console.error);
ws.on("message", function message(data) {
try {
const json_data = JSON.parse(data);
console.log(JSON.stringify(json_data));
if (json_data.message == messages.JOIN_LOBBY) {
console.log("Player wants to join lobby.");
waiting_players.push(ws);
waiting_player_ids.push(player_id);
if (waiting_players.length >= PLAYERS_IN_GAME) {
console.log("Lobby found!");
console.log(waiting_players);
/*
let lowest_id = -1;
for (let i = 0; i < PLAYERS_IN_GAME; i++) {
if (waiting_player_ids[i] < lowest_id || lowest_id == -1) {
lowest_id = waiting_player_ids[i];
}
}
for (let i = 0; i < PLAYERS_IN_GAME; i++) {
if (waiting_player_ids[i] == lowest_id) {
waiting_player_ids[i] = 1;
}
}
*/
for (let i = 0; i < PLAYERS_IN_GAME; i++) {
console.log(waiting_players[i]);
waiting_players[i].send(
JSON.stringify({
message: messages.PLAYERS_FOUND,
players: waiting_player_ids,
})
);
}
waiting_players = [];
waiting_player_ids = [];
}
}
if (json_data.message == messages.SEND_ICE_CANDIDATE) {
players[json_data.target].send(
JSON.stringify({
message: messages.RECEIVE_ICE_CANDIDATE,
from: player_id,
mid_name: json_data.mid_name,
index_name: json_data.index_name,
sdp_name: json_data.sdp_name,
})
);
}
if (json_data.message == messages.SEND_DESCRIPTION) {
console.log(json_data);
players[json_data.target].send(
JSON.stringify({
message: messages.RECEIVE_DESCRIPTION,
from: player_id,
data: json_data.data,
type: json_data.type,
})
);
}
} catch (e) {
console.log('Got strange data: "' + data + '"');
console.error(e);
}
});
ws.send(JSON.stringify({ message: messages.ASSIGN_ID, id: player_id }));
});
Client signaling (gdscript):
extends Node
class_name Signaling
@onready var web_rtc_manager : WebRTCManager = $"../WebRTC"
@onready var network_manager : NetworkManager = get_parent()
var socket = WebSocketPeer.new()
var waiting_for_join_request : bool = false
var my_id : int
var is_host : bool
var host_id : int = -1
enum messages {
ASSIGN_ID,
JOIN_LOBBY,
PLAYERS_FOUND,
SEND_ICE_CANDIDATE,
SEND_DESCRIPTION,
RECEIVE_ICE_CANDIDATE,
RECEIVE_DESCRIPTION,
}
func _ready():
socket.connect_to_url("ws://localhost:9396")
waiting_for_join_request = true
func _process(_delta):
socket.poll()
var state = socket.get_ready_state()
if state == WebSocketPeer.STATE_OPEN:
if waiting_for_join_request:
socket.send_text(JSON.stringify({"message":messages.JOIN_LOBBY}))
waiting_for_join_request = false
while socket.get_available_packet_count():
var packet_data : Dictionary = JSON.parse_string(socket.get_packet().get_string_from_utf8())
if packet_data.message == messages.ASSIGN_ID:
my_id = packet_data.id
web_rtc_manager.my_id = my_id
network_manager.id = my_id
web_rtc_manager.connected(my_id)
elif packet_data.message == messages.PLAYERS_FOUND:
web_rtc_manager.players_in_game = len(packet_data.players)
is_host = true
for player_id : int in packet_data.players:
web_rtc_manager.connect_to_player(player_id)
if player_id > my_id:
is_host = false
if player_id < host_id or host_id == -1:
host_id = player_id
network_manager.is_host = is_host
network_manager.host_id = host_id
print(packet_data.players)
print("Found players!")
elif packet_data.message == messages.RECEIVE_ICE_CANDIDATE:
web_rtc_manager.add_ice_candidate(packet_data.mid_name, packet_data.index_name, packet_data.sdp_name, packet_data.from)
elif packet_data.message == messages.RECEIVE_DESCRIPTION:
web_rtc_manager.set_remote_description(packet_data.type, packet_data.data, packet_data.from)
elif state == WebSocketPeer.STATE_CLOSING:
# Keep polling to achieve proper close.
pass
elif state == WebSocketPeer.STATE_CLOSED:
var code = socket.get_close_code()
var reason = socket.get_close_reason()
print("WebSocket closed with code: %d, reason %s. Clean: %s" % [code, reason, code != -1])
set_process(false) # Stop processing.
func send(message : messages, data : Dictionary, target : int):
data["message"] = message
data["target"] = target
socket.send_text(JSON.stringify(data))
func send_description(type : String, data : String, target : int):
send(messages.SEND_DESCRIPTION, {"data": data, "type": type}, target)
func send_ice_candidate(mid_name, index_name, sdp_name, target : int):
send(messages.SEND_ICE_CANDIDATE, {"mid_name":mid_name, "index_name":index_name, "sdp_name":sdp_name}, target)
WebRTC manager (gdscript):
extends Node
class_name WebRTCManager
@onready var signaling : Signaling = $"../Signaling"
var peer : WebRTCMultiplayerPeer = WebRTCMultiplayerPeer.new()
var my_id : int
var players_in_game : int
var connected_peers : int = 0
func _ready():
multiplayer.peer_connected.connect(peer_connected)
func connect_to_player(id : int):
var player_peer : WebRTCPeerConnection = WebRTCPeerConnection.new()
player_peer.initialize({
"iceServers" : [{ "urls": ["stun:stun.l.google.com:19302"] }]
})
player_peer.session_description_created.connect(offer_created.bind(id))
player_peer.ice_candidate_created.connect(ice_candidate_created.bind(id))
peer.add_peer(player_peer, id)
if id < my_id:
player_peer.create_offer()
func offer_created(type : String, data : String, id : int):
signaling.send_description(type, data, id)
func ice_candidate_created(mid_name, index_name, sdp_name, id : int):
signaling.send_ice_candidate(mid_name, index_name, sdp_name, id)
func add_ice_candidate(mid_name, index_name, sdp_name, id : int):
peer.get_peer(id).connection.add_ice_candidate(mid_name, index_name, sdp_name)
func set_remote_description(type : String, data : String, id : int):
peer.get_peer(id).connection.set_remote_description(type, data)
func connected(id):
peer.create_mesh(id)
multiplayer.multiplayer_peer = peer
func peer_connected(id):
print("Connection with " + str(id))
connected_peers += 1
if connected_peers == players_in_game - 1:
get_parent().connected_to_everyone()
@rpc("any_peer", "call_local")
func ping():
print("I got pinged!")
func _on_ping_button_pressed():
ping.rpc()
Yes, it's kinda complicated but it works.
1. Players are rigidbodies
2. Quicksand, https://fonts.google.com/specimen/Quicksand?query=quicksand
3. I change the scene