Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: simplified interest management #990

Draft
wants to merge 56 commits into
base: main
Choose a base branch
from
Draft
Changes from 1 commit
Commits
Show all changes
56 commits
Select commit Hold shift + click to select a range
b7d40e9
interest management bench tests implemented.
dragonslaya84 Nov 7, 2021
8fd5930
simplified aoi system. This is intital start of simplifying. I have g…
dragonslaya84 Nov 7, 2021
2dc52b8
null check fix.
dragonslaya84 Nov 7, 2021
4c67bee
more fixes to get tests to pass.
dragonslaya84 Nov 7, 2021
7322f46
fixing all prefabs with new scene checker and proximity scripts.
dragonslaya84 Nov 8, 2021
6312152
fix for lower version of cli unity.
dragonslaya84 Nov 8, 2021
8035029
more fixes for test's passing. Will fix scene checker tests later on.
dragonslaya84 Nov 8, 2021
a8e710c
proximity checker now fully works.
dragonslaya84 Nov 8, 2021
ae7f26c
improvements to core interest management system.
dragonslaya84 Nov 8, 2021
a06baef
more improvements to core of aoi. Now the system register's single ao…
dragonslaya84 Nov 10, 2021
abd394b
setup performance base to do proximity test alone now and fixed some …
dragonslaya84 Nov 10, 2021
5084838
some clean up.
dragonslaya84 Nov 10, 2021
acdf561
fix for non 2021.2 versions
dragonslaya84 Nov 10, 2021
1d24684
fix for causing removal of players from server list.
dragonslaya84 Nov 11, 2021
75773e9
removed match checker
dragonslaya84 Nov 12, 2021
c292a66
fixed issues with comparer check for registering new visibility systems.
dragonslaya84 Nov 12, 2021
bf51366
fix for opening up prefabs.
dragonslaya84 Nov 12, 2021
9248f20
pushing new default global system script so if end users want to have…
dragonslaya84 Nov 12, 2021
8a94b68
lowering the benchmark to 500 objects and 50 clients.
dragonslaya84 Nov 12, 2021
f44edbd
fixed up global system better. Made it so u dont need script now.
dragonslaya84 Nov 12, 2021
070f859
added lymdun suggestion use linq for finding list.
dragonslaya84 Nov 13, 2021
0527155
renamed somethings better
dragonslaya84 Nov 15, 2021
9d57d5d
fixing check
dragonslaya84 Nov 15, 2021
f817b6f
placed ignore setting for now on tests.
dragonslaya84 Nov 15, 2021
1450d7f
fix example.
dragonslaya84 Nov 15, 2021
dba2e1d
new script to do performance testing for global system only.
dragonslaya84 Nov 15, 2021
f17a202
improving test:
James-Frowen Nov 15, 2021
534a064
adding namespace to test
James-Frowen Nov 15, 2021
8efd797
test: removing multiclient component
James-Frowen Nov 15, 2021
256b4aa
lowering count to check it works
James-Frowen Nov 15, 2021
0a24a5a
moving set up before starting server
James-Frowen Nov 15, 2021
06ac691
fix: using OnStartServer for RegisterObject
James-Frowen Nov 15, 2021
36e6e48
rename: NetworkVisibility
James-Frowen Nov 15, 2021
fcdae19
rename: renaming visibilitySystemData
James-Frowen Nov 15, 2021
3b99788
style: moving Comparer to struct it is for
James-Frowen Nov 15, 2021
a46acd0
removing VisibilitySystemData
James-Frowen Nov 15, 2021
8ee2fd8
adding todo
James-Frowen Nov 15, 2021
66b1173
deleting VisibilitySystemData
James-Frowen Nov 15, 2021
7fa8251
throwing if object manager is null
James-Frowen Nov 15, 2021
da94d9f
creating settings once, and then settingsa values in OnStartServer
James-Frowen Nov 15, 2021
a650f83
rename CheckForObservers to Rebuild
James-Frowen Nov 15, 2021
6f40e06
renaming BaseVisibilityInspector
James-Frowen Nov 15, 2021
acb9ac7
remaing Initialize to CreateSystem
James-Frowen Nov 15, 2021
97455b0
deleting Interface
James-Frowen Nov 15, 2021
46e7dc0
making RegisterObject take the Network Identity
James-Frowen Nov 15, 2021
cdc9372
renaming rebuild methods
James-Frowen Nov 15, 2021
eb925de
fixing ServerObjectMamager
James-Frowen Nov 15, 2021
9eee2e8
removing SceneSettings
James-Frowen Nov 15, 2021
0bd0835
making ProximitySettings a struct
James-Frowen Nov 15, 2021
ddf3861
changing when system is created
James-Frowen Nov 15, 2021
79900a1
fixing startup order, key changes in comment
James-Frowen Nov 16, 2021
740f00f
Adding Server reference to Factories
James-Frowen Nov 16, 2021
c8f181d
test: adding helper methods to ensure things are added/destroyed corr…
James-Frowen Nov 16, 2021
5f1fae0
fixing helper methods
James-Frowen Nov 16, 2021
aeb08ba
test: fixing test helper methods, adding asserts for system not found
James-Frowen Nov 16, 2021
037b5b0
test: moving debug logs to its own test method
James-Frowen Nov 16, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
fixing ServerObjectMamager
making sure we still call IM functions are same time as before
- need to rebuild observers for player after setting character
- moving show to player to IM
- adding OnSpawn and OnDestroy instead of using world events (we need to control the order, our event might be called before/after user added events)
James-Frowen committed Nov 15, 2021

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
commit eb925de3252131da82133ff22e289cdb9d517e51
Original file line number Diff line number Diff line change
@@ -85,7 +85,7 @@ public override void RebuildForPlayer(INetworkPlayer player)
else if (Observers.ContainsKey(identity) && !Observers[identity].Contains(player))
Observers[identity].Add(player);

InterestManager.ServerObjectManager.ShowToPlayer(identity, player);
InterestManager.ShowToPlayer(identity, player);
}
}

@@ -113,14 +113,14 @@ public override void RebuildAll()
if (players != null && players.Contains(player)) continue;

Observers[identity].Add(player);
InterestManager.ServerObjectManager.ShowToPlayer(identity, player);
InterestManager.ShowToPlayer(identity, player);
}
else
{
if (players != null && !players.Contains(player)) continue;

Observers[identity].Remove(player);
InterestManager.ServerObjectManager.HideToPlayer(identity, player);
InterestManager.HideToPlayer(identity, player);
}
}
}
Original file line number Diff line number Diff line change
@@ -39,7 +39,7 @@ public void MoveToScene(Scene scene, NetworkIdentity identity)
{
foreach (INetworkPlayer player in Observers[identity])
{
InterestManager.ServerObjectManager.HideToPlayer(identity, player);
InterestManager.HideToPlayer(identity, player);
}

// Reset list to empty now.
@@ -54,7 +54,7 @@ public void MoveToScene(Scene scene, NetworkIdentity identity)
{
if (player.Identity.gameObject.scene.handle != scene.handle) continue;

InterestManager.ServerObjectManager.ShowToPlayer(identity, player);
InterestManager.ShowToPlayer(identity, player);
}
}

@@ -98,11 +98,11 @@ public override void RebuildForPlayer(INetworkPlayer player)
else if (Observers.ContainsKey(identity) && !Observers[identity].Contains(player))
Observers[identity].Add(player);

InterestManager.ServerObjectManager.ShowToPlayer(identity, player);
InterestManager.ShowToPlayer(identity, player);
}

// Always show self to them.
InterestManager.ServerObjectManager.ShowToPlayer(player.Identity, player);
InterestManager.ShowToPlayer(player.Identity, player);
}

/// <summary>
42 changes: 32 additions & 10 deletions Assets/Mirage/Runtime/InterestManagement/InterestManager.cs
Original file line number Diff line number Diff line change
@@ -17,8 +17,8 @@ public class InterestManager
private HashSet<INetworkPlayer> _observers = new HashSet<INetworkPlayer>();

private static readonly ProfilerMarker ObserverProfilerMarker = new ProfilerMarker(nameof(Observers));
private static readonly ProfilerMarker OnAuthenticatedProfilerMarker = new ProfilerMarker(nameof(OnAuthenticated));
private static readonly ProfilerMarker OnSpawnInWorldProfilerMarker = new ProfilerMarker(nameof(OnSpawnInWorld));
private static readonly ProfilerMarker OnAuthenticatedProfilerMarker = new ProfilerMarker(nameof(RebuildForPlayer));
private static readonly ProfilerMarker OnSpawnInWorldProfilerMarker = new ProfilerMarker(nameof(OnSpawn));
private static readonly ProfilerMarker OnUpdateProfilerMarker = new ProfilerMarker(nameof(Update));
private static readonly ProfilerMarker OnSendProfilerMarker = new ProfilerMarker(nameof(Send));

@@ -37,8 +37,7 @@ public class InterestManager
/// </summary>
private void OnServerStopped()
{
ServerObjectManager.Server.World.onSpawn -= OnSpawnInWorld;
ServerObjectManager.Server.Authenticated.RemoveListener(OnAuthenticated);
ServerObjectManager.Server.Authenticated.RemoveListener(RebuildForPlayer);

_visibilitySystems.Clear();
_observers.Clear();
@@ -49,16 +48,15 @@ private void OnServerStopped()
/// </summary>
private void OnServerStarted()
{
ServerObjectManager.Server.World.onSpawn += OnSpawnInWorld;
ServerObjectManager.Server.Authenticated.AddListener(OnAuthenticated);
ServerObjectManager.Server.Authenticated.AddListener(RebuildForPlayer);
}

/// <summary>
/// When player's finally authenticate to server we will check for visibility systems
/// and if any we will use that otherwise we will default to global system.
/// </summary>
/// <param name="player">The player we want to show or hide objects to.</param>
private void OnAuthenticated(INetworkPlayer player)
public void RebuildForPlayer(INetworkPlayer player)
{
OnAuthenticatedProfilerMarker.Begin();

@@ -75,7 +73,7 @@ private void OnAuthenticated(INetworkPlayer player)
{
foreach (NetworkIdentity identity in ServerObjectManager.Server.World.SpawnedIdentities)
{
ServerObjectManager.ShowToPlayer(identity, player);
ShowToPlayer(identity, player);
}
}

@@ -87,7 +85,7 @@ private void OnAuthenticated(INetworkPlayer player)
/// each system can do what they need or want with the info.
/// </summary>
/// <param name="identity">The newly spawned object.</param>
private void OnSpawnInWorld(NetworkIdentity identity)
internal void OnSpawn(NetworkIdentity identity)
{
OnSpawnInWorldProfilerMarker.Begin();

@@ -105,13 +103,20 @@ private void OnSpawnInWorld(NetworkIdentity identity)
{
foreach (INetworkPlayer player in ServerObjectManager.Server.Players)
{
ServerObjectManager.ShowToPlayer(identity, player);
ShowToPlayer(identity, player);
}
}

OnSpawnInWorldProfilerMarker.End();
}

internal void OnDestroy(NetworkIdentity identity)
{
Send(identity, new ObjectDestroyMessage { netId = identity.NetId });

// todo do we need to do anything else when an object is destoryed? (like remove it from systems)
}

#endregion

#region Class Specific
@@ -128,6 +133,23 @@ public InterestManager(ServerObjectManager serverObjectManager)
ServerObjectManager.Server?.Stopped.AddListener(OnServerStopped);
}

/// <summary>
/// Sends spawn message to player if it is not loading a scene
/// </summary>
/// <param name="identity"></param>
/// <param name="player"></param>
public void ShowToPlayer(NetworkIdentity identity, INetworkPlayer player)
{
// dont send if loading scene
if (player.SceneIsReady)
ServerObjectManager.SendSpawnMessage(identity, player);
}

public void HideToPlayer(NetworkIdentity identity, INetworkPlayer player)
{
player.Send(new ObjectHideMessage { netId = identity.NetId });
}

internal void Update()
{
OnUpdateProfilerMarker.Begin();
69 changes: 50 additions & 19 deletions Assets/Mirage/Runtime/ServerObjectManager.cs
Original file line number Diff line number Diff line change
@@ -71,6 +71,9 @@ public void Start()

public void Update()
{
// todo move this to NetworkServer
// NetworkServer should decide when things get rebuild not unity
// this'll be more important when we add tick stuff
InterestManager?.Update();
}

@@ -214,7 +217,7 @@ public void ReplaceCharacter(INetworkPlayer player, NetworkIdentity identity, bo

player.Identity = identity;

// Set the connection on the NetworkIdentity on the server, NetworkIdentity.SetLocalPlayer is not called on the server (it is on clients)
// Set the player on the NetworkIdentity on the server
identity.SetClientOwner(player);

// special case, we are in host mode, set hasAuthority to true so that all overrides see it
@@ -224,6 +227,11 @@ public void ReplaceCharacter(INetworkPlayer player, NetworkIdentity identity, bo
Server.LocalClient.Player.Identity = identity;
}

// add player to observers AFTER the character is set.
//
// IMPORTANT: do this in AddCharacter & ReplaceCharacter!
SpawnVisibleObjectForPlayer(player);

if (logger.LogEnabled()) logger.Log($"Replacing playerGameObject object netId: {identity.NetId} asset ID {identity.PrefabHash:X}");

Respawn(identity);
@@ -232,6 +240,20 @@ public void ReplaceCharacter(INetworkPlayer player, NetworkIdentity identity, bo
previousCharacter.RemoveClientAuthority();
}

void SpawnVisibleObjectForPlayer(INetworkPlayer player)
{
if (logger.LogEnabled()) logger.Log($"Checking Observers on {Server.World.SpawnedIdentities.Count} objects for player: {player}");

if (!player.SceneIsReady)
{
// client needs to finish loading scene before we can spawn objects
// otherwise it would not find scene objects.
return;
}

InterestManager.RebuildForPlayer(player);
}

/// <summary>
/// <para>When an <see cref="AddCharacterMessage"/> message handler has received a request from a player, the server calls this to associate the player object with the connection.</para>
/// <para>When a player is added for a connection, the client for that connection is made ready automatically. The player object is automatically spawned, so you do not need to call NetworkServer.Spawn for that object. This function is used for "adding" a player, not for "replacing" the player on a connection. If there is already a player on this playerControllerId for this connection, this will fail.</para>
@@ -324,23 +346,6 @@ void Respawn(NetworkIdentity identity)
}
}

/// <summary>
/// Sends spawn message to player if it is not loading a scene
/// </summary>
/// <param name="identity"></param>
/// <param name="player"></param>
public void ShowToPlayer(NetworkIdentity identity, INetworkPlayer player)
{
// dont send if loading scene
if (player.SceneIsReady)
SendSpawnMessage(identity, player);
}

public void HideToPlayer(NetworkIdentity identity, INetworkPlayer player)
{
player.Send(new ObjectHideMessage { netId = identity.NetId });
}

/// <summary>
/// Removes the character from a player, with the option to keep the player as the owner of the object
/// </summary>
@@ -508,6 +513,8 @@ public void Spawn(NetworkIdentity identity, INetworkPlayer owner)
}

if (logger.LogEnabled()) logger.Log($"SpawnObject instance ID {identity.NetId} asset ID {identity.PrefabHash:X}");

InterestManager.OnSpawn(identity);
}

internal void SendSpawnMessage(NetworkIdentity identity, INetworkPlayer player)
@@ -629,7 +636,7 @@ void DestroyObject(NetworkIdentity identity, bool destroyServerObject)
Server.World.RemoveIdentity(identity);
identity.Owner?.RemoveOwnedObject(identity);

InterestManager.Send(identity, new ObjectDestroyMessage { netId = identity.NetId });
InterestManager.OnDestroy(identity);

if (Server.LocalClientActive)
{
@@ -696,5 +703,29 @@ public void SpawnObjects()
}
}
}

/// <summary>
/// Sends spawn message for scene objects and other visible objects to the given player if it has a character
/// <para>
/// If there is a <see cref="Mirage.NetworkSceneManager"/> then this will be called after the client finishes loading the scene and sends <see cref="SceneReadyMessage"/>
/// </para>
/// </summary>
/// <param name="player">The player to spawn objects for</param>
public void SpawnVisibleObjects(INetworkPlayer player) => SpawnVisibleObjects(player, false);

/// <summary>
/// Sends spawn message for scene objects and other visible objects to the given player if it has a character
/// </summary>
/// <param name="player">The player to spawn objects for</param>
/// <param name="ignoreHasCharacter">If true will spawn visibile objects even if player does not have a spawned character yet</param>
// note: can't use optional param here because we need just NetworkPlayer version for event
public void SpawnVisibleObjects(INetworkPlayer player, bool ignoreHasCharacter)
{
if (logger.LogEnabled()) logger.Log("SpawnVisibleObjects for conn:" + player);

// client is ready to start spawning objects
if (ignoreHasCharacter || player.HasCharacter)
SpawnVisibleObjectForPlayer(player);
}
}
}
Original file line number Diff line number Diff line change
@@ -86,7 +86,7 @@ public IEnumerator ShowForPlayerTest() => UniTask.ToCoroutine(async () =>
serverPlayer.SceneIsReady = true;

// call ShowForConnection
serverObjectManager.ShowToPlayer(serverIdentity, serverPlayer);
serverObjectManager.InterestManager.ShowToPlayer(serverIdentity, serverPlayer);

// todo assert correct message was sent using Substitute for socket or player

2 changes: 1 addition & 1 deletion Assets/Tests/Runtime/Host/ServerObjectManagerTest.cs
Original file line number Diff line number Diff line change
@@ -20,7 +20,7 @@ public void HideForPlayerTest()

NetworkIdentity identity = new GameObject().AddComponent<NetworkIdentity>();

serverObjectManager.HideToPlayer(identity, player);
serverObjectManager.InterestManager.HideToPlayer(identity, player);

player.Received().Send(Arg.Is<ObjectHideMessage>(msg => msg.netId == identity.NetId));