Skip to content

Commit 9deb6ec

Browse files
update
Migrated the unique world setup into this branch. The world is created prior to starting NetworkManager completely. When using hybrid prefabs (i.e. mixed mode), the final portion of the NetworkManager's start logic (i.e. endpoint connection, etc.) is not invoked until the hybrid prefabs have been registered. Hybrid prefabs wait until the World is finished starting/being initialized.
1 parent a97064b commit 9deb6ec

7 files changed

Lines changed: 264 additions & 4 deletions

File tree

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
#if UNIFIED_NETCODE
2+
using System.Collections.Generic;
3+
using Unity.Collections;
4+
using Unity.Entities;
5+
using Unity.NetCode;
6+
7+
namespace Unity.Netcode.Components
8+
{
9+
10+
public struct NetcodeConnection
11+
{
12+
internal World World;
13+
internal Entity Entity;
14+
public int NetworkId;
15+
16+
public bool IsServer => World.IsServer();
17+
public void GoInGame()
18+
{
19+
World.EntityManager.AddComponentData(Entity, default(NetworkStreamInGame));
20+
}
21+
public void SendMessage<T>(T message) where T : unmanaged, IRpcCommand
22+
{
23+
var req = World.EntityManager.CreateEntity();
24+
World.EntityManager.AddComponentData(req, new SendRpcCommandRequest { TargetConnection = Entity });
25+
World.EntityManager.AddComponentData(req, message);
26+
}
27+
}
28+
29+
internal partial class UnifiedUpdateConnections : SystemBase
30+
{
31+
private List<NetcodeConnection> m_TempConnections = new List<NetcodeConnection>();
32+
protected override void OnUpdate()
33+
{
34+
var commandBuffer = new EntityCommandBuffer(Allocator.Temp);
35+
foreach (var (networkId, connectionState, entity) in SystemAPI.Query<NetworkId, ConnectionState>().WithNone<NetworkStreamConnection>().WithEntityAccess())
36+
{
37+
commandBuffer.RemoveComponent<ConnectionState>(entity);
38+
m_TempConnections.Add(new NetcodeConnection { World = World, Entity = entity, NetworkId = networkId.Value });
39+
}
40+
foreach (var con in m_TempConnections)
41+
{
42+
NetworkManager.OnNetCodeDisconnect?.Invoke(con);
43+
}
44+
45+
m_TempConnections.Clear();
46+
47+
foreach (var (networkId, entity) in SystemAPI.Query<NetworkId>().WithAll<NetworkStreamConnection>().WithNone<NetworkStreamInGame>().WithEntityAccess())
48+
{
49+
commandBuffer.AddComponent<NetworkStreamInGame>(entity);
50+
commandBuffer.AddComponent(entity, default(ConnectionState));
51+
m_TempConnections.Add(new NetcodeConnection { World = World, Entity = entity, NetworkId = networkId.Value });
52+
}
53+
54+
foreach (var con in m_TempConnections)
55+
{
56+
NetworkManager.OnNetCodeConnect?.Invoke(con);
57+
}
58+
59+
m_TempConnections.Clear();
60+
61+
commandBuffer.Playback(EntityManager);
62+
}
63+
64+
protected override void OnDestroy()
65+
{
66+
var commandBuffer = new EntityCommandBuffer(Allocator.Temp);
67+
foreach (var (networkId, entity) in SystemAPI.Query<NetworkId>().WithEntityAccess())
68+
{
69+
commandBuffer.RemoveComponent<ConnectionState>(entity);
70+
// TODO: maybe disconnect reason?
71+
m_TempConnections.Add(new NetcodeConnection { World = World, Entity = entity, NetworkId = networkId.Value });
72+
}
73+
foreach (var con in m_TempConnections)
74+
{
75+
NetworkManager.OnNetCodeDisconnect?.Invoke(con);
76+
}
77+
commandBuffer.Playback(EntityManager);
78+
base.OnDestroy();
79+
}
80+
}
81+
}
82+
#endif

com.unity.netcode.gameobjects/Runtime/Components/Helpers/UnifiedUpdateConnections.cs.meta

Lines changed: 2 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

com.unity.netcode.gameobjects/Runtime/Components/NetworkObjectBridge.cs

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,13 @@
44

55
namespace Unity.Netcode
66
{
7-
// Temporarily making this public
8-
// TODO: Make this internal when complete (if used)
7+
8+
/// <summary>
9+
/// TODO-UNIFIED: Would need to be reviewed for alternate ways of handling this.
10+
/// </summary>
11+
/// <remarks>
12+
/// If used, we most likely would make this internal
13+
/// </remarks>
914
public partial class NetworkObjectBridge : GhostBehaviour
1015
{
1116
public Action<ulong> NetworkObjectIdChanged;
@@ -58,6 +63,11 @@ public override void OnDestroy()
5863
}
5964
}
6065

66+
/// <summary>
67+
/// TODO-UNIFIED: Would need to be reviewed for alternate ways of handling this.
68+
/// Creates the hosted world and provides a means to configuring
69+
/// the 2nd port for unified netcode connection.
70+
/// </summary>
6171
internal class UnifiedBootStrap : ClientServerBootstrap
6272
{
6373
public static UnifiedBootStrap Instance { get; private set; }

com.unity.netcode.gameobjects/Runtime/Configuration/NetworkPrefabs.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -279,6 +279,7 @@ public bool Contains(NetworkPrefab prefab)
279279

280280
#if UNIFIED_NETCODE
281281
internal bool HasPendingGhostPrefabs { get; private set; }
282+
internal bool HasGhostPrefabs { get; private set; }
282283
private List<NetworkPrefab> m_PendingGhostRegistration = new List<NetworkPrefab>();
283284

284285
/// <summary>
@@ -341,6 +342,7 @@ private bool AddPrefabRegistration(NetworkPrefab networkPrefab)
341342
if (networkPrefab.HasGhost)
342343
{
343344
HasPendingGhostPrefabs = true;
345+
HasGhostPrefabs = true;
344346
m_PendingGhostRegistration.Add(networkPrefab);
345347
}
346348
#endif

com.unity.netcode.gameobjects/Runtime/Core/NetworkBehaviour.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
using System;
22
using System.Collections.Generic;
33
using Unity.Collections;
4+
#if MULTIPLAYER_TOOLS && (DEVELOPMENT_BUILD || UNITY_EDITOR || UNITY_MP_TOOLS_NET_STATS_MONITOR_ENABLED_IN_RELEASE)
5+
using System.Runtime.CompilerServices;
6+
#endif
47
using UnityEngine;
58

69
namespace Unity.Netcode

com.unity.netcode.gameobjects/Runtime/Core/NetworkManager.cs

Lines changed: 158 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
using System;
22
using System.Collections.Generic;
3-
using Unity.Collections;
43
using System.Linq;
4+
using Unity.Collections;
5+
#if UNIFIED_NETCODE
6+
using Unity.Entities;
7+
#endif
58
using Unity.Netcode.Components;
69
using Unity.Netcode.Runtime;
710
using UnityEngine;
@@ -12,6 +15,7 @@
1215
using UnityEngine.SceneManagement;
1316
using Debug = UnityEngine.Debug;
1417

18+
1519
namespace Unity.Netcode
1620
{
1721
/// <summary>
@@ -1045,6 +1049,10 @@ private void Awake()
10451049
#endif
10461050
// Notify we have instantiated a new instance of NetworkManager.
10471051
OnInstantiated?.Invoke(this);
1052+
1053+
#if UNIFIED_NETCODE && UNITY_MULTIPLAYER_PLAYMODE
1054+
MPPMCheckInternal.Initialize();
1055+
#endif
10481056
}
10491057

10501058
private void OnEnable()
@@ -1307,6 +1315,35 @@ private bool CanStart(StartType type)
13071315
return true;
13081316
}
13091317

1318+
#if UNIFIED_NETCODE
1319+
private System.Collections.IEnumerator WaitForHybridPrefabRegistration(StartType startType)
1320+
{
1321+
while (NetworkConfig.Prefabs.HasPendingGhostPrefabs)
1322+
{
1323+
yield return null;
1324+
}
1325+
1326+
switch (startType)
1327+
{
1328+
case StartType.Server:
1329+
{
1330+
InternalStartServer();
1331+
break;
1332+
}
1333+
case StartType.Host:
1334+
{
1335+
InternalStartHost();
1336+
break;
1337+
}
1338+
case StartType.Client:
1339+
{
1340+
InternalStartClient();
1341+
break;
1342+
}
1343+
}
1344+
}
1345+
#endif
1346+
13101347
/// <summary>
13111348
/// Starts a server
13121349
/// </summary>
@@ -1331,6 +1368,25 @@ public bool StartServer()
13311368

13321369
Initialize(true);
13331370

1371+
#if UNIFIED_NETCODE
1372+
// TODO-UNIFIED: Review and align on this being a way to handle knowing if the world should be created.
1373+
if (NetworkConfig.Prefabs.HasGhostPrefabs)
1374+
{
1375+
DefaultWorldInitialization.Initialize("Default World", false);
1376+
StartCoroutine(WaitForHybridPrefabRegistration(StartType.Server));
1377+
return true;
1378+
}
1379+
else
1380+
{
1381+
return InternalStartServer();
1382+
}
1383+
#else
1384+
return InternalStartServer();
1385+
#endif
1386+
}
1387+
1388+
internal bool InternalStartServer()
1389+
{
13341390
try
13351391
{
13361392
IsListening = NetworkConfig.NetworkTransport.StartServer();
@@ -1354,7 +1410,6 @@ public bool StartServer()
13541410
IsListening = false;
13551411
throw;
13561412
}
1357-
13581413
return IsListening;
13591414
}
13601415

@@ -1381,6 +1436,27 @@ public bool StartClient()
13811436

13821437
Initialize(false);
13831438

1439+
#if UNIFIED_NETCODE
1440+
// TODO-UNIFIED: Review and align on this being a way to handle knowing if the world should be created.
1441+
if (NetworkConfig.Prefabs.HasGhostPrefabs)
1442+
{
1443+
DefaultWorldInitialization.Initialize("Default World", false);
1444+
StartCoroutine(WaitForHybridPrefabRegistration(StartType.Client));
1445+
// TODO-UNIFIED: Need a way to signal everything completed.
1446+
return true;
1447+
}
1448+
else
1449+
{
1450+
return InternalStartClient();
1451+
}
1452+
#else
1453+
return InternalStartClient();
1454+
#endif
1455+
1456+
}
1457+
1458+
internal bool InternalStartClient()
1459+
{
13841460
try
13851461
{
13861462
IsListening = NetworkConfig.NetworkTransport.StartClient();
@@ -1404,6 +1480,7 @@ public bool StartClient()
14041480
return IsListening;
14051481
}
14061482

1483+
14071484
/// <summary>
14081485
/// Starts a Host
14091486
/// </summary>
@@ -1426,6 +1503,28 @@ public bool StartHost()
14261503
}
14271504

14281505
Initialize(true);
1506+
1507+
#if UNIFIED_NETCODE
1508+
// TODO-UNIFIED: Review and align on this being a way to handle knowing if the world should be created.
1509+
if (NetworkConfig.Prefabs.HasGhostPrefabs)
1510+
{
1511+
DefaultWorldInitialization.Initialize("Default World", false);
1512+
StartCoroutine(WaitForHybridPrefabRegistration(StartType.Host));
1513+
// TODO-UNIFIED: Need a way to signal everything completed.
1514+
return true;
1515+
}
1516+
else
1517+
{
1518+
return InternalStartHost();
1519+
}
1520+
#else
1521+
return InternalStartHost();
1522+
#endif
1523+
1524+
}
1525+
1526+
internal bool InternalStartHost()
1527+
{
14291528
try
14301529
{
14311530
IsListening = NetworkConfig.NetworkTransport.StartServer();
@@ -1645,6 +1744,23 @@ internal void ShutdownInternal()
16451744
IsListening = false;
16461745
m_ShuttingDown = false;
16471746

1747+
1748+
#if UNIFIED_NETCODE
1749+
// TODO-UNIFIED: Review and align on this being a way to handle knowing if the world should be created.
1750+
if (NetworkConfig.Prefabs.HasGhostPrefabs)
1751+
{
1752+
try
1753+
{
1754+
// Dispose of all worlds
1755+
World.DisposeAllWorlds();
1756+
}
1757+
catch (Exception ex)
1758+
{
1759+
Debug.LogException(ex);
1760+
}
1761+
}
1762+
#endif
1763+
16481764
// Generate a local notification that the host client is disconnected
16491765
if (IsHost)
16501766
{
@@ -1683,6 +1799,7 @@ internal void ShutdownInternal()
16831799
// can unsubscribe from tick updates and such.
16841800
NetworkTimeSystem?.Shutdown();
16851801
NetworkTickSystem = null;
1802+
16861803
}
16871804

16881805
// Ensures that the NetworkManager is cleaned up before OnDestroy is run on NetworkObjects and NetworkBehaviours when quitting the application.
@@ -1948,5 +2065,44 @@ internal static void OnOneTimeTearDown()
19482065
}
19492066
#endif
19502067

2068+
#if UNIFIED_NETCODE
2069+
// TODO-UNIFIED: We might not need all of this (i.e. UnifiedUpdateConnections might be handled differently in unified)
2070+
public delegate void OnConnectDelegate(NetcodeConnection connection);
2071+
public delegate void OnDisconnectDelegate(NetcodeConnection connection);
2072+
public static OnConnectDelegate OnNetCodeConnect;
2073+
public static OnDisconnectDelegate OnNetCodeDisconnect;
2074+
2075+
#if UNITY_EDITOR
2076+
// TODO-UNIFIED: For POC only (centralizing)
2077+
public static MPPMCheckInfo MPPMCheck => MPPMCheckInternal;
2078+
internal static MPPMCheckInfo MPPMCheckInternal = new MPPMCheckInfo();
2079+
public class MPPMCheckInfo
2080+
{
2081+
public bool Installed { get; private set; }
2082+
public bool HasServerTag;
2083+
public bool HasClientTag;
2084+
internal void Initialize()
2085+
{
2086+
#if UNITY_MULTIPLAYER_PLAYMODE
2087+
Installed = true;
2088+
var tags = Multiplayer.PlayMode.CurrentPlayer.Tags;
2089+
foreach (var tag in tags)
2090+
{
2091+
if (tag == "Server")
2092+
{
2093+
HasServerTag = true;
2094+
}
2095+
else if (tag == "Client")
2096+
{
2097+
HasClientTag = true;
2098+
}
2099+
}
2100+
#else
2101+
Installed = false;
2102+
#endif
2103+
}
2104+
}
2105+
#endif
2106+
#endif
19512107
}
19522108
}

com.unity.netcode.gameobjects/Runtime/Unity.Netcode.Runtime.asmdef

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,11 @@
9494
"name": "com.unity.netcode",
9595
"expression": "1.10.1",
9696
"define": "UNIFIED_NETCODE"
97+
},
98+
{
99+
"name": "com.unity.multiplayer.playmode",
100+
"expression": "0.1.0",
101+
"define": "UNITY_MULTIPLAYER_PLAYMODE"
97102
}
98103
],
99104
"noEngineReferences": false

0 commit comments

Comments
 (0)