Skip to content

Commit 711a072

Browse files
committed
Added Observer system
1 parent c816086 commit 711a072

13 files changed

+389
-89
lines changed

MLAPI-Editor/NetworkedObjectEditor.cs

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ public class NetworkedObjectEditor : Editor
99
{
1010
private bool initialized;
1111
private NetworkedObject networkedObject;
12+
private bool showObservers;
1213

1314
private void Init()
1415
{
@@ -44,7 +45,23 @@ public override void OnInspectorGUI()
4445
EditorGUILayout.LabelField("isOwner: ", networkedObject.isOwner.ToString(), EditorStyles.label);
4546
EditorGUILayout.LabelField("isPoolObject: ", networkedObject.isPlayerObject.ToString(), EditorStyles.label);
4647
EditorGUILayout.LabelField("isPlayerObject: ", networkedObject.isPlayerObject.ToString(), EditorStyles.label);
47-
//EditorGUILayout.LabelField("ServerOnly: ", networkedObject.ServerOnly.ToString(), EditorStyles.label);
48+
49+
if (networkedObject.observers != null && networkedObject.observers.Count > 0)
50+
{
51+
showObservers = EditorGUILayout.Foldout(showObservers, "Observers");
52+
if (showObservers)
53+
{
54+
EditorGUI.indentLevel += 1;
55+
foreach (var o in networkedObject.observers)
56+
{
57+
if (NetworkingManager.singleton.ConnectedClients[o].PlayerObject != null)
58+
EditorGUILayout.ObjectField("ClientId: " + o, NetworkingManager.singleton.ConnectedClients[o].PlayerObject, typeof(GameObject), false);
59+
else
60+
EditorGUILayout.TextField("ClientId: " + o, EditorStyles.label);
61+
}
62+
EditorGUI.indentLevel -= 1;
63+
}
64+
}
4865
}
4966
}
5067
}

MLAPI/Data/SyncedVarField.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
using System.Reflection;
1+
using System.Collections.Generic;
2+
using System.Reflection;
23

34
namespace MLAPI.Data
45
{

MLAPI/MLAPI.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@
8484
<Compile Include="GlobalSuppressions.cs" />
8585
<Compile Include="MonoBehaviours\Prototyping\NetworkedAnimator.cs" />
8686
<Compile Include="MonoBehaviours\Prototyping\NetworkedNavMeshAgent.cs" />
87+
<Compile Include="MonoBehaviours\Prototyping\NetworkedProximity.cs" />
8788
<Compile Include="NetworkingManagerComponents\Binary\BitWriter.cs" />
8889
<Compile Include="NetworkingManagerComponents\Binary\BitReader.cs" />
8990
<Compile Include="NetworkingManagerComponents\Binary\BinaryHelpers.cs" />

MLAPI/MonoBehaviours/Core/NetworkedBehaviour.cs

Lines changed: 103 additions & 57 deletions
Large diffs are not rendered by default.

MLAPI/MonoBehaviours/Core/NetworkedObject.cs

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using MLAPI.Data;
2+
using MLAPI.NetworkingManagerComponents.Binary;
23
using MLAPI.NetworkingManagerComponents.Core;
34
using System;
45
using System.Collections.Generic;
@@ -114,6 +115,73 @@ public bool isSpawned
114115
internal bool _isSpawned = false;
115116
internal bool? sceneObject = null;
116117

118+
public HashSet<uint> observers = new HashSet<uint>();
119+
120+
internal void RebuildObservers(uint? clientId = null)
121+
{
122+
bool initial = clientId != null;
123+
if (initial)
124+
{
125+
bool shouldBeAdded = true;
126+
for (int i = 0; i < childNetworkedBehaviours.Count; i++)
127+
{
128+
bool state = childNetworkedBehaviours[i].OnCheckObserver(clientId.Value);
129+
if (state == false)
130+
{
131+
shouldBeAdded = false;
132+
break;
133+
}
134+
}
135+
if (shouldBeAdded)
136+
observers.Add(clientId.Value);
137+
}
138+
else
139+
{
140+
HashSet<uint> previousObservers = new HashSet<uint>(observers);
141+
HashSet<uint> newObservers = new HashSet<uint>();
142+
bool update = false;
143+
for (int i = 0; i < childNetworkedBehaviours.Count; i++)
144+
{
145+
bool changed = childNetworkedBehaviours[i].OnRebuildObservers(newObservers);
146+
if (changed)
147+
{
148+
observers = newObservers;
149+
update = true;
150+
break;
151+
}
152+
}
153+
if (update)
154+
{
155+
foreach (KeyValuePair<uint, NetworkedClient> pair in NetworkingManager.singleton.connectedClients)
156+
{
157+
if (new NetId(pair.Key).IsHost())
158+
continue;
159+
if ((previousObservers.Contains(pair.Key) && !newObservers.Contains(pair.Key)) ||
160+
(!previousObservers.Contains(pair.Key) && newObservers.Contains(pair.Key)))
161+
{
162+
//Something changed for this client.
163+
using (BitWriter writer = new BitWriter())
164+
{
165+
writer.WriteUInt(networkId);
166+
writer.WriteBool(observers.Contains(pair.Key));
167+
168+
InternalMessageHandler.Send(pair.Key, "MLAPI_SET_VISIBILITY", "MLAPI_INTERNAL", writer.Finalize(), null);
169+
}
170+
FlushToClient(pair.Key);
171+
}
172+
}
173+
}
174+
}
175+
}
176+
177+
internal void SetLocalVisibility(bool visibility)
178+
{
179+
for (int i = 0; i < childNetworkedBehaviours.Count; i++)
180+
{
181+
childNetworkedBehaviours[i].OnSetLocalVisibility(visibility);
182+
}
183+
}
184+
117185
private void OnDestroy()
118186
{
119187
if (NetworkingManager.singleton != null)

MLAPI/MonoBehaviours/Core/NetworkingManager.cs

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -384,6 +384,7 @@ private ConnectionConfig Init(bool server)
384384
MessageManager.messageTypes.Add("MLAPI_COMMAND", 12);
385385
MessageManager.messageTypes.Add("MLAPI_RPC", 13);
386386
MessageManager.messageTypes.Add("MLAPI_TARGET", 14);
387+
MessageManager.messageTypes.Add("MLAPI_SET_VISIBILITY", 15);
387388

388389
List<MessageType> messageTypes = new List<MessageType>(NetworkConfig.MessageTypes)
389390
{
@@ -761,7 +762,7 @@ private void Update()
761762
if (NetworkConfig.ConnectionApproval)
762763
writer.WriteByteArray(NetworkConfig.ConnectionData);
763764

764-
InternalMessageHandler.Send(netId.GetClientId(), "MLAPI_CONNECTION_REQUEST", "MLAPI_INTERNAL", writer.Finalize(), null, null, true);
765+
InternalMessageHandler.Send(netId.GetClientId(), "MLAPI_CONNECTION_REQUEST", "MLAPI_INTERNAL", writer.Finalize(), null, null, null, true);
765766
}
766767
}
767768
break;
@@ -1032,6 +1033,12 @@ private void HandleIncomingData(uint clientId, byte[] data, int channelId)
10321033
InternalMessageHandler.HandleTargetRpc(clientId, incommingData, channelId);
10331034
}
10341035
break;
1036+
case 15:
1037+
if (isClient)
1038+
{
1039+
InternalMessageHandler.HandleSetVisibility(clientId, incommingData, channelId);
1040+
}
1041+
break;
10351042
}
10361043
#endregion
10371044
}
@@ -1051,6 +1058,9 @@ internal void DisconnectClient(uint clientId)
10511058
if (diffieHellmanPublicKeys.ContainsKey(clientId))
10521059
diffieHellmanPublicKeys.Remove(clientId);
10531060

1061+
foreach (KeyValuePair<uint, NetworkedObject> pair in SpawnManager.spawnedObjects)
1062+
pair.Value.observers.Remove(clientId);
1063+
10541064
NetId netId = new NetId(clientId);
10551065
if (netId.IsHost() || netId.IsInvalid())
10561066
return;
@@ -1080,10 +1090,13 @@ internal void OnClientDisconnect(uint clientId)
10801090

10811091
if (isServer)
10821092
{
1093+
foreach (KeyValuePair<uint, NetworkedObject> pair in SpawnManager.spawnedObjects)
1094+
pair.Value.observers.Remove(clientId);
1095+
10831096
using (BitWriter writer = new BitWriter())
10841097
{
10851098
writer.WriteUInt(clientId);
1086-
InternalMessageHandler.Send("MLAPI_CLIENT_DISCONNECT", "MLAPI_INTERNAL", writer.Finalize(), clientId);
1099+
InternalMessageHandler.Send("MLAPI_CLIENT_DISCONNECT", "MLAPI_INTERNAL", writer.Finalize(), clientId, null);
10871100
}
10881101
}
10891102
}
@@ -1098,7 +1111,7 @@ private void SyncTime()
10981111

10991112
byte[] buffer = writer.Finalize();
11001113
foreach (KeyValuePair<uint, NetworkedClient> pair in connectedClients)
1101-
InternalMessageHandler.Send("MLAPI_TIME_SYNC", "MLAPI_TIME_SYNC", buffer);
1114+
InternalMessageHandler.Send("MLAPI_TIME_SYNC", "MLAPI_TIME_SYNC", buffer, null);
11021115
}
11031116
}
11041117

@@ -1147,7 +1160,7 @@ internal void HandleApproval(uint clientId, bool approved, Vector3 position, Qua
11471160
connectedClients[clientId].PlayerObject = go;
11481161
}
11491162

1150-
int amountOfObjectsToSend = SpawnManager.spawnedObjects.Values.Count();
1163+
int amountOfObjectsToSend = SpawnManager.spawnedObjects.Values.Count;
11511164

11521165
using (BitWriter writer = new BitWriter())
11531166
{
@@ -1179,12 +1192,15 @@ internal void HandleApproval(uint clientId, bool approved, Vector3 position, Qua
11791192

11801193
foreach (KeyValuePair<uint, NetworkedObject> pair in SpawnManager.spawnedObjects)
11811194
{
1195+
pair.Value.RebuildObservers(clientId); //Rebuilds observers for the new client
1196+
11821197
writer.WriteBool(pair.Value.isPlayerObject);
11831198
writer.WriteUInt(pair.Value.NetworkId);
11841199
writer.WriteUInt(pair.Value.OwnerClientId);
11851200
writer.WriteInt(NetworkConfig.NetworkPrefabIds[pair.Value.NetworkedPrefabName]);
11861201
writer.WriteBool(pair.Value.gameObject.activeInHierarchy);
11871202
writer.WriteBool(pair.Value.sceneObject == null ? true : pair.Value.sceneObject.Value);
1203+
writer.WriteBool(pair.Value.observers.Contains(clientId));
11881204

11891205
writer.WriteFloat(pair.Value.transform.position.x);
11901206
writer.WriteFloat(pair.Value.transform.position.y);
@@ -1196,7 +1212,7 @@ internal void HandleApproval(uint clientId, bool approved, Vector3 position, Qua
11961212
}
11971213
}
11981214

1199-
InternalMessageHandler.Send(clientId, "MLAPI_CONNECTION_APPROVED", "MLAPI_INTERNAL", writer.Finalize(), null, null, true);
1215+
InternalMessageHandler.Send(clientId, "MLAPI_CONNECTION_APPROVED", "MLAPI_INTERNAL", writer.Finalize(), null, null, null, true);
12001216

12011217
if (OnClientConnectedCallback != null)
12021218
OnClientConnectedCallback.Invoke(clientId);
@@ -1213,6 +1229,7 @@ internal void HandleApproval(uint clientId, bool approved, Vector3 position, Qua
12131229
writer.WriteUInt(clientId);
12141230
writer.WriteInt(-1);
12151231
writer.WriteBool(false);
1232+
writer.WriteBool(connectedClients[clientId].PlayerObject.GetComponent<NetworkedObject>().observers.Contains(clientId));
12161233

12171234
writer.WriteFloat(connectedClients[clientId].PlayerObject.transform.position.x);
12181235
writer.WriteFloat(connectedClients[clientId].PlayerObject.transform.position.y);
@@ -1227,7 +1244,7 @@ internal void HandleApproval(uint clientId, bool approved, Vector3 position, Qua
12271244
writer.WriteUInt(clientId);
12281245
}
12291246

1230-
InternalMessageHandler.Send("MLAPI_ADD_OBJECT", "MLAPI_INTERNAL", writer.Finalize(), clientId);
1247+
InternalMessageHandler.Send("MLAPI_ADD_OBJECT", "MLAPI_INTERNAL", writer.Finalize(), clientId, null);
12311248
}
12321249
//Flush syncvars:
12331250
foreach (KeyValuePair<uint, NetworkedObject> networkedObject in SpawnManager.spawnedObjects)
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
using MLAPI.MonoBehaviours.Core;
2+
using System.Collections.Generic;
3+
using UnityEngine;
4+
5+
namespace MLAPI.MonoBehaviours.Prototyping
6+
{
7+
//This class based on the code from the UNET HLAPI Proximity
8+
public class NetworkedProximity : NetworkedBehaviour
9+
{
10+
public enum CheckMethod
11+
{
12+
Physics3D,
13+
Physics2D
14+
};
15+
16+
[Tooltip("The maximum range that objects will be visible at.")]
17+
public int Range = 10;
18+
19+
[Tooltip("How often (in seconds) that this object should update the set of players that can see it.")]
20+
public float VisibilityUpdateInterval = 1.0f; // in seconds
21+
22+
[Tooltip("Which method to use for checking proximity of players.\n\nPhysics3D uses 3D physics to determine proximity.\n\nPhysics2D uses 2D physics to determine proximity.")]
23+
public CheckMethod CheckType = CheckMethod.Physics3D;
24+
25+
[Tooltip("Enable to force this object to be hidden from players.")]
26+
public bool ForceHidden = false;
27+
28+
private float lastUpdateTime;
29+
30+
private void Update()
31+
{
32+
if (!isServer)
33+
return;
34+
35+
if (Time.time - lastUpdateTime > VisibilityUpdateInterval)
36+
{
37+
RebuildObservers();
38+
lastUpdateTime = NetworkingManager.singleton.NetworkTime;
39+
}
40+
}
41+
42+
public override bool OnCheckObserver(uint newClientId)
43+
{
44+
if (ForceHidden)
45+
return false;
46+
Vector3 pos = NetworkingManager.singleton.ConnectedClients[newClientId].PlayerObject.transform.position;
47+
return (pos - transform.position).magnitude < Range;
48+
}
49+
50+
public override bool OnRebuildObservers(HashSet<uint> observers)
51+
{
52+
if (ForceHidden)
53+
{
54+
// ensure player can still see themself
55+
if (networkedObject != null && networkedObject.isPlayerObject)
56+
observers.Add(networkedObject.OwnerClientId);
57+
return true;
58+
}
59+
60+
switch (CheckType)
61+
{
62+
case CheckMethod.Physics3D:
63+
{
64+
var hits = Physics.OverlapSphere(transform.position, Range);
65+
for (int i = 0; i < hits.Length; i++)
66+
{
67+
var uv = hits[i].GetComponent<NetworkedObject>();
68+
if (uv != null && uv.isPlayerObject)
69+
observers.Add(uv.OwnerClientId);
70+
}
71+
return true;
72+
}
73+
case CheckMethod.Physics2D:
74+
{
75+
var hits = Physics2D.OverlapCircleAll(transform.position, Range);
76+
for (int i = 0; i < hits.Length; i++)
77+
{
78+
var uv = hits[i].GetComponent<NetworkedObject>();
79+
if (uv != null && (uv.isPlayerObject))
80+
observers.Add(uv.OwnerClientId);
81+
}
82+
return true;
83+
}
84+
}
85+
return false;
86+
}
87+
}
88+
}

MLAPI/MonoBehaviours/Prototyping/NetworkedTransform.cs

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -122,12 +122,13 @@ private void Update()
122122
writer.Write(transform.position.x);
123123
writer.Write(transform.position.y);
124124
writer.Write(transform.position.z);
125+
125126
writer.Write(transform.rotation.eulerAngles.x);
126127
writer.Write(transform.rotation.eulerAngles.y);
127128
writer.Write(transform.rotation.eulerAngles.z);
128129
}
129130
if (isServer)
130-
SendToClientsTarget("MLAPI_OnRecieveTransformFromServer", "MLAPI_POSITION_UPDATE", positionUpdateBuffer);
131+
SendToClientsTarget("MLAPI_OnRecieveTransformFromServer", "MLAPI_POSITION_UPDATE", positionUpdateBuffer, true);
131132
else
132133
SendToServerTarget("MLAPI_OnRecieveTransformFromClient", "MLAPI_POSITION_UPDATE", positionUpdateBuffer);
133134
}
@@ -160,9 +161,11 @@ private void OnRecieveTransformFromServer(uint clientId, byte[] data)
160161
float xPos = reader.ReadSingle();
161162
float yPos = reader.ReadSingle();
162163
float zPos = reader.ReadSingle();
164+
163165
float xRot = reader.ReadSingle();
164166
float yRot = reader.ReadSingle();
165167
float zRot = reader.ReadSingle();
168+
166169
lerpStartPos = transform.position;
167170
lerpStartRot = transform.rotation;
168171
lerpEndPos = new Vector3(xPos, yPos, zPos);
@@ -181,9 +184,11 @@ private void OnRecieveTransformFromClient(uint clientId, byte[] data)
181184
float xPos = reader.ReadSingle();
182185
float yPos = reader.ReadSingle();
183186
float zPos = reader.ReadSingle();
187+
184188
float xRot = reader.ReadSingle();
185189
float yRot = reader.ReadSingle();
186190
float zRot = reader.ReadSingle();
191+
187192
if (InterpolateServer)
188193
{
189194
lerpStartPos = transform.position;
@@ -215,13 +220,13 @@ private void OnRecieveTransformFromClient(uint clientId, byte[] data)
215220
{
216221
if (Vector3.Distance(NetworkingManager.singleton.connectedClients[i].PlayerObject.transform.position, transform.position) <= ProximityRange)
217222
{
218-
SendToClientTarget(NetworkingManager.singleton.connectedClients[i].ClientId, "MLAPI_OnRecieveTransformFromServer", "MLAPI_POSITION_UPDATE", positionUpdateBuffer);
223+
SendToClientTarget(NetworkingManager.singleton.connectedClients[i].ClientId, "MLAPI_OnRecieveTransformFromServer", "MLAPI_POSITION_UPDATE", positionUpdateBuffer, true);
219224
}
220225
}
221226
}
222227
else
223228
{
224-
SendToNonLocalClientsTarget("MLAPI_OnRecieveTransformFromServer", "MLAPI_POSITION_UPDATE", positionUpdateBuffer);
229+
SendToNonLocalClientsTarget("MLAPI_OnRecieveTransformFromServer", "MLAPI_POSITION_UPDATE", positionUpdateBuffer, true);
225230
}
226231
}
227232
}

0 commit comments

Comments
 (0)