Broadcast a LAN Multiplayer Game
Code and workflows to send and receive broadcast packets to join multiplayer sessions

What you'll develop on this page

Broadcasting and joining a game on two different machines that are on the same LAN
Our server will broadcast its IP address over LAN and clients will be able to see all LAN servers broadcasting so they can select and join.

Creating UdpConnection

UdpClient

We are going to create a new class called UdpConnection which will have methods to both send and receive UDP broadcast packets. Our implementation works off of MattijsKneppers' great start in the Unity forums.
The core component of broadcasting will be UdpClient from .NET. It is important to note that this broadcasting method is not "Unity-approved"; we are using a Microsoft technology to get this done.
On the server side we will create a new UdpClient. We will create a "sendToEndpoint," which will be our broadcasting IP address and broadcasting port. We will then use UdpClient's "send" method to send data over to that endpoint.
The broadcasting IP address we recommend is "255.255.255.255"
There is material online that says this is a bad address to use because some routers ignore broadcasts to this address. This has not been the case in our testing.
If you find that IP address to be wonky in your development, or know of a better approach, please let us know on our Discord.
On the client side we will also create a UdpClient. We will bind on the broadcasting port to receive the messages sent in a broadcast at that port. We will then listen for messages.
Doesn't this mean that we'll just be broadcasting to ourselves and as a result we'll just be constantly receiving the messages we just sent, because we are binding and sending on the same port?!
Great point! And that's why we will only create a UdpConnection to broadcast in MainScene (the game) when we are the server. There'll be no clients that will also be broadcasting when joining the server. We will only be "listening" for broadcasts in NavigationScene (title menu).
For testing on the same machine we will make a build, then hardwire a port change for our editor player just to check if it works.

Thread

Listening for broadcast packets is a "blocking" activity, which means that this activity blocks a thread while it awaits a message.
We do not want to block all of Unity while we listen for broadcast messages. So, we're going to create a separate thread to handle listening for messages. Enter: Microsoft's Thread class.
Although this approach is also not "sanctioned" by Unity, it has never caused an issue throughout all of our testing.

Serialized JSON

Finally, what kind of message are we sending?
We will be serializing our data as JSON objects which contain - game name - server IP address - timestamp of when message was sent (server tick)
We will be serializing and deserializing our data using JsonUtility. This approach is a common pattern shown in the Unity docs.

NETWORKING IS HARD

We have tested this broadcasting on Windows/Linux/Mac desktops and iOS devices.
The broadcasting/pick up works great in "normal" cases (super majority of cases). "Normal" cases mean when devices are using "built in" wifi or ethernet.
We have gotten mixed results with "wacky" cases. "Wacky" cases are like a desktop computer using a usb dongle for wifi, or like if you are connecting through a VM so everything is "virtualized." In these types of cases, you may experience trouble with broadcasting or picking up broadcasts when using our methods in this gitbook.
Why? Well when machines have a Network Interface Controller (NIC) and additional methods to connect to the internet, it is hard to "automatically" know which IP endpoint to bind to. (Don't worry you don't need to know this stuff, just know "wacky" situations mean it's hard to know the right answer without asking the user).
To handle these "wacky" situations we can: 1) build a UI component into the app that asks the user and potentially add confusion, 2) program a more robust sending mechanism that sends across all interfaces or, 3) choose the most likely one and hope for the best.
In this gitbook,we went with approach #3. (If it turns out that we chose the wrong option for you all, please let us know in our Discord and we will update).
Additionally, you may find (like we did) a lot of answers on Stack Overflow telling you not to do broadcasting, and instead to do multicasting! It is "way better and recommended!"
Do not listen to those charlatans! You will spend countless hours testing, and retesting, and then after days of using Wireshark, and tracing packets, and learning more than you would ever like about networking data layers and IGMP packets, and learn that it is completely unknown how many routers support this functionality and that there is no way to really configure a router to see if it can support it.
Oh us? No, no we're not bitter....

UdpConnection

Without further ado...
    Create a new script in the Multiplayer Setup folder called UdpConnection
    Paste this code snippet into UdpConnection.cs:
1
using System.Collections;
2
using System.Collections.Generic;
3
using UnityEngine;
4
using System;
5
using System.Text;
6
using System.Net;
7
using System.Net.NetworkInformation;
8
using System.Net.Sockets;
9
using System.Threading.Tasks;
10
using System.Threading;
11
12
13
//
14
// "silent hero award" for this implementation
15
// https://forum.unity.com/threads/simple-udp-implementation-send-read-via-mono-c.15900/#post-3645256
16
//
17
public class UdpConnection
18
{
19
//In this variable we will store our actual udpClient object (from Microsoft)
20
private UdpClient udpClient;
21
22
//This is the broadcast address that we will be passed from the server for where to send our messages
23
private string sendToIp;
24
//This is the broadcast port, we either bind to it and listen on it as a client
25
//or we bind to it and SEND to it as the server
26
//It actually doesn't matter whhat port we bind on as the server, as long as we send to this port
27
//but we decided to just bind to it as well to keep track of less numbers (it does mean we need to do)
28
private int sendOrReceivePort;
29
30
//This is a Queue of our messages (where we store received broadcast messages)
31
private readonly Queue<string> incomingQueue = new Queue<string>();
32
//This is the thread we will start to "listen" on
33
Thread receiveThread;
34
//We need to know if we were listening on a thread so we know whether to turn it off when we don't need it
35
//If we are the server this will stay false
36
private bool threadRunning = false;
37
//The server will need to find its IP address so it can send it out to clients
38
private IPAddress m_MyIp;
39
40
//We call this method as a way to initialize our UdpConnection
41
//We pass through the broadcast address (sendToIp) and the broadcast port (sendOrReceivePort)
42
public void StartConnection(string sendToIp, int sendOrReceivePort)
43
{
44
//We create our udpClient by binding it to the sendOrReceivePort
45
//Binding to the broadcast port really only matters if you are a client listening for our broadcast messages
46
//The server could actually bind to any port
47
try { udpClient = new UdpClient(sendOrReceivePort); }
48
catch (Exception e)
49
{
50
Debug.Log("Failed to listen for UDP at port " + sendOrReceivePort + ": " + e.Message);
51
return;
52
}
53
// "best tip of all time award" to MichaelBluestein
54
// https://forums.xamarin.com/discussion/comment/1206/#Comment_1206
55
// somehow you get IP address
56
foreach (var netInterface in NetworkInterface.GetAllNetworkInterfaces()) {
57
if (netInterface.OperationalStatus == OperationalStatus.Up &&
58
netInterface.NetworkInterfaceType == NetworkInterfaceType.Wireless80211 ||
59
netInterface.NetworkInterfaceType == NetworkInterfaceType.Ethernet) {
60
foreach (var addrInfo in netInterface.GetIPProperties().UnicastAddresses) {
61
if (addrInfo.Address.AddressFamily == AddressFamily.InterNetwork) {
62
63
//We will use this address to broadcast out to clients as the server
64
m_MyIp = addrInfo.Address;
65
}
66
}
67
}
68
}
69
//Now we configure our udpClient to be able to broadcast
70
udpClient.EnableBroadcast = true;
71
72
//We set our broadcast IP and broadcast port
73
this.sendToIp = sendToIp;
74
this.sendOrReceivePort = sendOrReceivePort;
75
}
76
77
//This will only be called by the client in order to start "listening"
78
public void StartReceiveThread()
79
{
80
//We create our new thread that be running the method "ListenForMessages"
81
receiveThread = new Thread(() => ListenForMessages(udpClient));
82
//We configure the thread we just created
83
receiveThread.IsBackground = true;
84
//We note that it is running so we don't forget to turn it off
85
threadRunning = true;
86
//Now we start the thread
87
receiveThread.Start();
88
}
89
90
//This method is called by StartReceiveThread()
91
private void ListenForMessages(UdpClient client)
92
{
93
//We create our listening endpoint
94
IPEndPoint remoteIpEndPoint = new IPEndPoint(IPAddress.Any, 0);
95
96
//We will continue running this until we turn "threadRunning" to false (which is when we don't need to listen anymore)
97
while (threadRunning)
98
{
99
try
100
{
101
//A little console log to know we have started listening
102
Debug.Log("starting receive on " + m_MyIp.ToString() +" and port " +sendOrReceivePort.ToString());
103
104
// Blocks until a message returns on this socket from a remote host.
105
Byte[] receiveBytes = client.Receive(ref remoteIpEndPoint);
106
//We grab our byte stream as UTF8 encoding
107
string returnData = Encoding.UTF8.GetString(receiveBytes);
108
109
//We enqueue our received byte stream
110
lock (incomingQueue)
111
{
112
incomingQueue.Enqueue(returnData);
113
}
114
}
115
//Error handling
116
catch (SocketException e)
117
{
118
// 10004 thrown when socket is closed
119
if (e.ErrorCode != 10004) Debug.Log("Socket exception while receiving data from udp client: " + e.Message);
120
}
121
catch (Exception e)
122
{
123
Debug.Log("Error receiving data from udp client: " + e.Message);
124
}
125
126
//We take a pause after receiving a message and run it again
127
Thread.Sleep(1);
128
}
129
}
130
131
//This is another method the client will call to grab all the messages that have been received by listening
132
public ServerInfoObject[] getMessages()
133
{
134
//We created an array of pending messages
135
string[] pendingMessages = new string[0];
136
//We create an array where we will store our ServerInfoObjects (how we store the JSON)
137
ServerInfoObject[] pendingServerInfos = new ServerInfoObject[0];
138
//While we get this done we need to lock the Queue
139
lock (incomingQueue)
140
{
141
//We set our pending messages the length of our queue of byte stream
142
pendingMessages = new string[incomingQueue.Count];
143
//We set our pending server infos the length of our queue of byte stream
144
pendingServerInfos = new ServerInfoObject[incomingQueue.Count];
145
146
//We will go through all our messages and update to get an array of ServerInfoObjects
147
int i = 0;
148
while (incomingQueue.Count != 0)
149
{
150
//We start moving data from the queue to our pending messages
151
pendingMessages[i] = incomingQueue.Dequeue();
152
//We then take our pending message
153
string jsonObject = pendingMessages[i];
154
//And use FromJson to create our array of ServerInfoObjects
155
pendingServerInfos[i] = JsonUtility.FromJson<ServerInfoObject>(jsonObject);
156
i++;
157
}
158
}
159
//We return an array of ServerInfoObjects to the client that called this method
160
return pendingServerInfos;
161
}
162
163
//We will only call this method on the server and provide it the game name and time
164
//We don't provide the game name in StartConnection because the client won't have it and
165
//both the client and server use StartConnection
166
public void Send(float floatTime, string gameName)
167
{
168
//All our values need to be string to be able to be serialized
169
string stringTime = floatTime.ToString();
170
171
//We need to create our destination endpoint
172
//It will be at the provided broadcast IP address and port
173
IPEndPoint sendToEndpoint = new IPEndPoint(IPAddress.Parse(sendToIp), sendOrReceivePort);
174
175
//We create a new ServerInfoObject which we will use to store our data
176
ServerInfoObject thisServerInfoObject = new ServerInfoObject();
177
//We populate our ServerInfoObject with data
178
thisServerInfoObject.gameName = gameName;
179
thisServerInfoObject.ipAddress = m_MyIp.ToString();
180
thisServerInfoObject.timeStamp = stringTime;
181
182
//Then we turn it into JSON
183
string json = JsonUtility.ToJson(thisServerInfoObject);
184
//Then we create a sendBytes array the size of the bytes of the JSON
185
Byte[] sendBytes = Encoding.UTF8.GetBytes(json);
186
//We then call send method on udpClient to send our byte array
187
udpClient.Send(sendBytes, sendBytes.Length, sendToEndpoint);
188
}
189
190
public void Stop()
191
{
192
// Not always UdpClients are used for listening
193
// Which is what requires the running thread to listen
194
if (threadRunning == true)
195
{
196
threadRunning = false;
197
receiveThread.Abort();
198
}
199
udpClient.Close();
200
udpClient.Dispose();
201
}
202
}
203
204
//This is our ServerInfoObject that we will be using to help us send data as JSON
205
[Serializable]
206
public class ServerInfoObject
207
{
208
public string gameName = "";
209
public string ipAddress = "";
210
public string timeStamp = "";
211
212
}
Copied!
Creating UdpConnection
We have a class that allows either the server to send messages or a client to receive messages
    We created UdpConnection

Broadcasting from the server

Now that we have UdpConnection we need to create a script to pull the broadcast IP address, port, and game name from ClientServerInfo and send a broadcast message
    Navigate to MainScene, right-click on the Hierarchy, and create an empty GameObject called GameBroadcasting
    With GameBroadcasting selected in Hierarchy, click "Add Component" in the Inspector and make a new script called "GameServerBroadcasting"
      Move GameServerBroadcasting into the Multiplayer Setup folder
Creating GameServerBroadcasting in GameBroadcasting
    Paste the code snippet below into GameServerBroadcasting.cs:
1
using System.Collections;
2
using System.Collections.Generic;
3
using UnityEngine;
4
using System;
5
using System.Text;
6
using System.Net;
7
using System.Net.Sockets;
8
using System.Threading.Tasks;
9
using System.Threading;
10
11
public class GameServerBroadcasting : MonoBehaviour
12
{
13
//We will be using our UdpConnection class to send messages
14
private UdpConnection connection;
15
16
//This will decide how often we send a broadcast messages
17
//We found that sending a broadcast message once every 2 seconds worked well
18
//you don't want to flood the network with broadcast packets
19
public float perSecond = .5f;
20
private float nextTime = 0;
21
22
//We will pull in game and broadcast information through ClientServerInfo
23
public ClientServerInfo ClientServerInfo;
24
25
void Start()
26
{
27
//We only need to run this if we are the server, otherwise disable
28
if (!ClientServerInfo.IsServer)
29
{
30
this.enabled = false;
31
}
32
33
//Get the broadcasting address and port from ClientServerInfo
34
string sendToIp = ClientServerInfo.BroadcastIpAddress;
35
int sendToPort = ClientServerInfo.BroadcastPort;
36
37
//First we create our class
38
connection = new UdpConnection();
39
//Then we run the initialization method and provide the broadcast IP address and port
40
connection.StartConnection(sendToIp, sendToPort);
41
}
42
43
void Update()
44
{
45
//We check if it is time to send another broadcast
46
if (Time.time >= nextTime)
47
{
48
//If it is we provide the Send method the game name and time
49
//These will be bundled with the server's IP address (which is generated in StartConnection)
50
//to be included in the broadcast packet
51
connection.Send(nextTime, ClientServerInfo.GameName);
52
nextTime += (1/perSecond);
53
}
54
}
55
56
void OnDestroy()
57
{
58
//If the server destroys this scene (by returning to NavigationScene) we will call the clean up method
59
connection.Stop();
60
}
61
}
Copied!
Updating GameServerBroadcasting
    Now select GameBroadcasting in Hierarchy, and drag the ClientServerInfo GameObject (also in Hierarchy) into the appropriate field in the GameServerBroadcasting component in Inspector
Updating GameBroadcasting GameObject
Now the server can send broadcast messages when in MainScene
    We created a new GameBroadcasting GameObject in MainScene
    We added GameServerBroadcasting component

Listening and joining on the client

We are going to need to listen for the broadcast messages in NavigationScene. Instead of having LocalGamesFinder search for GameObjects, we will update LocalGamesFinder to listen for broadcast messages.
We will then need to update what happens when we click on the list item, so we need to populate JoinGameScreen with the data sent in the broadcast packet.
    Navigate to NavigationScene and then open LocalGamesFinder
    Paste the code snippet below into LocalGamesFinder.cs:
1
using System;
2
using System.Collections;
3
using System.Collections.Generic;
4
using UnityEngine;
5
using UnityEngine.UIElements;
6
using UnityEditor;
7
8
public class LocalGamesFinder : MonoBehaviour
9
{
10
//We will be pulling in our SourceAsset from TitleScreenUI GameObject so we can reference Visual Elements
11
public UIDocument m_TitleUIDocument;
12
13
//When we grab the rootVisualElement of our UIDocument we will be able to query the TitleScreenManager Visual Element
14
private VisualElement m_titleScreenManagerVE;
15
16
//We will query for our TitleScreenManager cVE by its name "TitleScreenManager"
17
private TitleScreenManager m_titleScreenManagerClass;
18
19
//Within TitleScreenManager (which is everything) we will query for our list-view by name
20
//We don't have to query for the TitleScreen THEN list-view because it is one big tree of elements
21
//We can call any child from the parent, very convenient! But you must be mindful about being dilligent about
22
//creating unique names or else you can get back several elements (which at times is the point of sharing a name)
23
private ListView m_ListView;
24
25
//This is where we will store our received broadcast messages
26
private List<ServerInfoObject> discoveredServerInfoObjects = new List<ServerInfoObject>();
27
28
//This is our ListItem uxml that we will drag to the public field
29
//We need a reference to the uxml so we can build it in makeItem
30
public VisualTreeAsset m_localGameListItemAsset;
31
32
//These variables are used in Update() to pace how often we check for GameObjects
33
public float perSecond = 1.0f;
34
private float nextTime = 0;
35
36
///The broadcast ip address and port to be used by the server across the LAN
37
public string BroadcastIpAddress = "255.255.255.255";
38
public ushort BroadcastPort = 8014;
39
40
//We will be storing our UdpConnection class as connection
41
private UdpConnection connection;
42
43
void OnEnable()
44
{
45
//Here we grab the SourceAsset rootVisualElement
46
//This is a MAJOR KEY, really couldn't find this key step in information online
47
//If you want to reference your active UI in a script make a public UIDocument variable and
48
//then call rootVisualElement on it, from there you can query the Visual Element tree by names
49
//or element types
50
m_titleScreenManagerVE = m_TitleUIDocument.rootVisualElement;
51
//Here we grab the TitleScreenManager by querying by name
52
m_titleScreenManagerClass = m_titleScreenManagerVE.Q<TitleScreenManager>("TitleScreenManager");
53
//From within TitleScreenManager we query local-games-list by name
54
m_ListView = m_titleScreenManagerVE.Q<ListView>("local-games-list");
55
56
}
57
58
// Start is called before the first frame update
59
void Start()
60
{
61
//First we pull our broadcast IP address and port from our source of truth, which is this component
62
//We actually don't need the broadcast IP address when listening but we provide it anyway because the method
63
//requires both arguments (we could provide any IP address and it wouldn't matter, only the server needs to provide the right one)
64
string broadcastIp = BroadcastIpAddress;
65
//This is the port we will be listening on (this has to be the same as the port the server is sending on)
66
int receivePort = BroadcastPort;
67
68
//Next we create our UdpConnection class
69
connection = new UdpConnection();
70
//We provide our broadcast IP adress and port
71
connection.StartConnection(broadcastIp, receivePort);
72
//Then we start our receive thread which means "listen"
73
//This will start creating our queue of received messages that we will call in update
74
connection.StartReceiveThread();
75
76
77
// The three spells you must cast to conjure a list view
78
m_ListView.makeItem = MakeItem;
79
m_ListView.bindItem = BindItem;
80
m_ListView.itemsSource = discoveredServerInfoObjects;
81
82
}
83
84
private VisualElement MakeItem()
85
{
86
//Here we take the uxml and make a VisualElement
87
VisualElement listItem = m_localGameListItemAsset.CloneTree();
88
return listItem;
89
90
}
91
92
private void BindItem(VisualElement e, int index)
93
{
94
//We add the game name to the label of the list item
95
e.Q<Label>("game-name").text = discoveredServerInfoObjects[index].gameName;
96
97
//Here we create a call back for clicking on the list item and provide data to a function
98
e.Q<Button>("join-local-game").RegisterCallback<ClickEvent>(ev => ClickedJoinGame(discoveredServerInfoObjects[index]));
99
100
}
101
102
void ClickedJoinGame(ServerInfoObject localGame)
103
{
104
//We query our JoinGameScreen cVE and call a new function LoadJoinScreenForSelectedServer and pass our GameObject
105
//This is an example of clicking a list item and passing through data to a new function with that click
106
//You will see in our JoinGameScreen cVE that we use this data to fill labels in the view
107
m_titleScreenManagerClass.Q<JoinGameScreen>("JoinGameScreen").LoadJoinScreenForSelectedServer(localGame);
108
109
//We then call EnableJoinScreen on our TitleScreenManager cVE (which displays JoinGameScreen)
110
m_titleScreenManagerClass.EnableJoinScreen();
111
112
}
113
114
// Update is called once per frame
115
void Update()
116
{
117
if (Time.time >= nextTime)
118
{
119
//We grab our array of ServerInfoObjects from our UdpConnection class
120
foreach (ServerInfoObject serverInfo in connection.getMessages())
121
{
122
//We call ReceivedServerInfo so we can check if this ServerInfoObject contains new information
123
//We don't use it immediatly and add it to our list because it might already be in the list
124
ReceivedServerInfo(serverInfo);
125
}
126
//We increment
127
nextTime += (1/perSecond);
128
}
129
}
130
131
void ReceivedServerInfo(ServerInfoObject serverInfo)
132
{
133
//Filter to see if this ServerInfoObject matches with previous broadcasts
134
//We will start by thinking that it does not exist
135
bool ipExists = false;
136
137
foreach (ServerInfoObject discoveredInfo in discoveredServerInfoObjects)
138
{
139
//Check if this discovered ip address is already known
140
if (serverInfo.ipAddress == discoveredInfo.ipAddress)
141
{
142
ipExists = true;
143
144
//If a ServerInfoObject with this IP address has been discovered, when did we hear about it?
145
float receivedTime = float.Parse(serverInfo.timeStamp);
146
//What about this broadcast?
147
float storedTime = float.Parse(discoveredInfo.timeStamp);
148
149
//We will update to the latest information from the IP address that has been broadcast
150
//The host might have quit and started a new game and we want to display the latest info
151
if (receivedTime > storedTime)
152
{
153
//Set the data to the new data
154
discoveredInfo.gameName = serverInfo.gameName;
155
discoveredInfo.timeStamp = serverInfo.timeStamp;
156
//Now we need to update the table
157
m_ListView.Refresh();
158
}
159
}
160
161
}
162
//If the ip didn't already exist, add it to the known list
163
if (!ipExists)
164
{
165
//We add it to the list
166
discoveredServerInfoObjects.Add(serverInfo);
167
//We refresh our list to display the new data
168
m_ListView.Refresh();
169
}
170
}
171
172
//We must call the clean up function on UdpConnection or else the thread will keep running!
173
void OnDestroy()
174
{
175
connection.Stop();
176
}
177
}
Copied!
Updating LocalGamesFinder to listen for messages
    Now that we have updated LocalGamesFinder to update the list with the latest unique broadcasts we need to update JoinGameScreen custom Visual Element (cVE) to take in the new passed-through ServerInfoObject data
    Paste the code snippet below into JoinGameScreen.cs (cVE):
1
using System;
2
using System.Text;
3
using System.Net;
4
using System.Net.Sockets;
5
using System.Net.NetworkInformation;
6
using System.Collections;
7
using System.Threading.Tasks;
8
using System.Threading;
9
using System.Collections.Generic;
10
using UnityEngine;
11
using UnityEngine.UIElements;
12
using Unity.Entities;
13
using Unity.NetCode;
14
using UnityEngine.SceneManagement;
15
16
public class JoinGameScreen : VisualElement
17
{
18
Label m_GameName;
19
Label m_GameIp;
20
TextField m_PlayerName;
21
String m_HostName = "";
22
IPAddress m_MyIp;
23
24
public new class UxmlFactory : UxmlFactory<JoinGameScreen, UxmlTraits> { }
25
26
public JoinGameScreen()
27
{
28
this.RegisterCallback<GeometryChangedEvent>(OnGeometryChange);
29
}
30
31
void OnGeometryChange(GeometryChangedEvent evt)
32
{
33
//
34
// PROVIDE ACCESS TO THE FORM ELEMENTS THROUGH VARIABLES
35
//
36
m_GameName = this.Q<Label>("game-name");
37
m_GameIp = this.Q<Label>("game-ip");
38
m_PlayerName = this.Q<TextField>("player-name");
39
40
//Grab the system name
41
m_HostName = Dns.GetHostName();
42
//Set the value equal to the host name to start
43
m_PlayerName.value = m_HostName;
44
45
this.UnregisterCallback<GeometryChangedEvent>(OnGeometryChange);
46
}
47
48
public void LoadJoinScreenForSelectedServer(ServerInfoObject localGame)
49
{
50
51
m_GameName = this.Q<Label>("game-name");
52
m_GameIp = this.Q<Label>("game-ip");
53
m_GameName.text = localGame.gameName;
54
m_GameIp.text = localGame.ipAddress;
55
}
56
}
Copied!
    Now delete all the LocalGame GameObjects in the NavigationScene Hierarchy
    Save the NavigationScene
    Navigate to the BuildSettings folder, select the configuration file of your development platform (i.e. "macOS - Build"), then go to Inspector and hit Build and Run
    Change the port in line 47 in UdpConnection to 9001
      We make this change so that we don't bind on same port when testing
1
try { udpClient = new UdpClient(9001); }
Copied!
    Hit play in the editor
    Host a game in the editor and check out the build
      Remember to host in the editor, not the build, when testing
      The editor must send to the hardwired broadcast port
Changing the used port in the editor and hosting a game
    Great, we see our broadcasted game
    In the editor: quit the game, and then start a new game with a new name
    We can see our game name change in our build
    In the editor: click on the broadcasted game and join the game
Joining a broadcasted game
    Change the Player Settings to allow for a resizable window
      File > Build Settings > Player Settings button in the bottom left corner
        No gif here, we believe in you 💪
We are now able to join broadcasted games
    We updated LocalGamesFinder
    We updated JoinGameScreen cVE
    We updated the port in UdpConnection for testing
    We built our project and was able to broadcast and join a game
Github branch link:
git clone https://github.com/moetsi/Unity-DOTS-Multiplayer-XR-Sample/ git checkout 'Broadcasting-and-Joining-on-LAN'
Last modified 2mo ago