Skip to content

Commit

Permalink
refactor: remove local visibility hacks (MirageNet#696)
Browse files Browse the repository at this point in the history
The NetworkVisibility disabled the renderers in host mode.
This is just a hack and it is unnecesary.

With this patch,  host mode just sees all objects.
If the user wants to limit how much the host player sees,
they can do it just as easily by changing the far clipping plane in the camera,
or by using unity's LOD component https://docs.unity3d.com/Manual/LevelOfDetail.html
or implementing whatever logic they want with layers.

BREAKING CHANGE: NetworkVisibility no longer disables renderers in host mode
  • Loading branch information
paulpach committed Mar 13, 2021
1 parent 8af4471 commit df499ab
Show file tree
Hide file tree
Showing 5 changed files with 1 addition and 116 deletions.
13 changes: 1 addition & 12 deletions Assets/Mirage/Runtime/ClientObjectManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ void OnClientSceneChanged(string scenePath, SceneOperation sceneOperation)
internal void RegisterHostHandlers()
{
Client.Connection.RegisterHandler<ObjectDestroyMessage>(OnHostClientObjectDestroy);
Client.Connection.RegisterHandler<ObjectHideMessage>(OnHostClientObjectHide);
Client.Connection.RegisterHandler<ObjectHideMessage>(msg => { });
Client.Connection.RegisterHandler<SpawnMessage>(OnHostClientSpawn);
Client.Connection.RegisterHandler<ServerRpcReply>(OnServerRpcReply);
// host mode reuses objects in the server
Expand Down Expand Up @@ -519,16 +519,6 @@ internal void OnHostClientObjectDestroy(ObjectDestroyMessage msg)
SpawnedObjects.Remove(msg.netId);
}

internal void OnHostClientObjectHide(ObjectHideMessage msg)
{
if (logger.LogEnabled()) logger.Log("ClientScene::OnLocalObjectObjHide netId:" + msg.netId);

if (SpawnedObjects.TryGetValue(msg.netId, out NetworkIdentity localObject) && localObject != null)
{
localObject.OnSetHostVisibility(false);
}
}

internal void OnHostClientSpawn(SpawnMessage msg)
{
if (SpawnedObjects.TryGetValue(msg.netId, out NetworkIdentity localObject) && localObject != null)
Expand All @@ -541,7 +531,6 @@ internal void OnHostClientSpawn(SpawnMessage msg)
localObject.HasAuthority = msg.isOwner;
localObject.NotifyAuthority();
localObject.StartClient();
localObject.OnSetHostVisibility(true);
CheckForLocalPlayer(localObject);
}
}
Expand Down
34 changes: 0 additions & 34 deletions Assets/Mirage/Runtime/NetworkIdentity.cs
Original file line number Diff line number Diff line change
Expand Up @@ -712,14 +712,6 @@ internal void StopAuthority()
OnStopAuthority?.Invoke();
}

internal void OnSetHostVisibility(bool visible)
{
if (Visibility != null)
{
Visibility.OnSetHostVisibility(visible);
}
}

/// <summary>
/// check if observer can be seen by connection.
/// <list type="bullet">
Expand Down Expand Up @@ -1042,32 +1034,6 @@ public void RebuildObservers(bool initialize)
observers.Add(conn);
}
}

// special case for host mode: we use SetHostVisibility to hide
// NetworkIdentities that aren't in observer range from host.
// this is what games like Dota/Counter-Strike do too, where a host
// does NOT see all players by default. they are in memory, but
// hidden to the host player.
//
// this code is from UNET, it's a bit strange but it works:
// * it hides newly connected identities in host mode
// => that part was the intended behaviour
// * it hides ALL NetworkIdentities in host mode when the host
// connects but hasn't selected a character yet
// => this only works because we have no .localConnection != null
// check. at this stage, localConnection is null because
// StartHost starts the server first, then calls this code,
// then starts the client and sets .localConnection. so we can
// NOT add a null check without breaking host visibility here.
// * it hides ALL NetworkIdentities in server-only mode because
// observers never contain the 'null' .localConnection
// => that was not intended, but let's keep it as it is so we
// don't break anything in host mode. it's way easier than
// iterating all identities in a special function in StartHost.
if (initialize && !newObservers.Contains(Server.LocalConnection))
{
OnSetHostVisibility(false);
}
}

// remove all old .observers that aren't in newObservers anymore
Expand Down
10 changes: 0 additions & 10 deletions Assets/Mirage/Runtime/NetworkVisibility.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,15 +28,5 @@ public abstract class NetworkVisibility : NetworkBehaviour
/// <param name="initialize">True if the set of observers is being built for the first time.</param>
public abstract void OnRebuildObservers(HashSet<INetworkPlayer> observers, bool initialize);

/// <summary>
/// Callback used by the visibility system for objects on a host.
/// <para>Objects on a host (with a local client) cannot be disabled or destroyed when they are not visible to the local client. So this function is called to allow custom code to hide these objects. A typical implementation will disable renderer components on the object. This is only called on local clients on a host.</para>
/// </summary>
/// <param name="visible">New visibility state.</param>
public virtual void OnSetHostVisibility(bool visible)
{
foreach (Renderer rend in GetComponentsInChildren<Renderer>())
rend.enabled = visible;
}
}
}
57 changes: 0 additions & 57 deletions Assets/Tests/Editor/NetworkIdentityCallbackTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,28 +13,6 @@ public class NetworkIdentityCallbackTests
{
#region test components

class SetHostVisibilityExceptionNetworkBehaviour : NetworkVisibility
{
public override void OnRebuildObservers(HashSet<INetworkPlayer> observers, bool initialize) { }
public override bool OnCheckObserver(INetworkPlayer conn) { return true; }
public override void OnSetHostVisibility(bool visible)
{
throw new Exception("some exception");
}
}

class SetHostVisibilityNetworkBehaviour : NetworkVisibility
{
public int called;
public override void OnRebuildObservers(HashSet<INetworkPlayer> observers, bool initialize) { }
public override bool OnCheckObserver(INetworkPlayer conn) { return true; }
public override void OnSetHostVisibility(bool visible)
{
++called;
base.OnSetHostVisibility(visible);
}
}

class CheckObserverExceptionNetworkBehaviour : NetworkVisibility
{
public int called;
Expand All @@ -46,7 +24,6 @@ public override bool OnCheckObserver(INetworkPlayer conn)
valuePassed = conn;
throw new Exception("some exception");
}
public override void OnSetHostVisibility(bool visible) { }
}

class CheckObserverTrueNetworkBehaviour : NetworkVisibility
Expand All @@ -58,7 +35,6 @@ public override bool OnCheckObserver(INetworkPlayer conn)
++called;
return true;
}
public override void OnSetHostVisibility(bool visible) { }
}

class CheckObserverFalseNetworkBehaviour : NetworkVisibility
Expand All @@ -70,7 +46,6 @@ public override bool OnCheckObserver(INetworkPlayer conn)
++called;
return false;
}
public override void OnSetHostVisibility(bool visible) { }
}

class SerializeTest1NetworkBehaviour : NetworkBehaviour
Expand Down Expand Up @@ -137,20 +112,12 @@ public override void OnRebuildObservers(HashSet<INetworkPlayer> observers, bool
{
observers.Add(observer);
}
public override void OnSetHostVisibility(bool visible) { }
}

class RebuildEmptyObserversNetworkBehaviour : NetworkVisibility
{
public override bool OnCheckObserver(INetworkPlayer conn) { return true; }
public override void OnRebuildObservers(HashSet<INetworkPlayer> observers, bool initialize) { }
public int hostVisibilityCalled;
public bool hostVisibilityValue;
public override void OnSetHostVisibility(bool visible)
{
++hostVisibilityCalled;
hostVisibilityValue = visible;
}
}

#endregion
Expand Down Expand Up @@ -498,18 +465,6 @@ public void NotifyAuthorityCallsOnStartStopAuthority()
stopAuthFunc.Received(1).Invoke();
}

[Test]
public void OnSetHostVisibilityCallsComponentsAndCatchesExceptions()
{
// add component
gameObject.AddComponent<SetHostVisibilityExceptionNetworkBehaviour>();

Assert.Throws<Exception>(() =>
{
identity.OnSetHostVisibility(true);
});
}

[Test]
public void OnCheckObserverCatchesException()
{
Expand Down Expand Up @@ -864,17 +819,5 @@ public void RebuildObserversAddsReadyServerConnectionsIfNotImplemented()
Assert.That(identity.observers, Is.EquivalentTo(new[] { readyConnection }));
}

[Test]
public void OnSetHostVisibilityBaseTest()
{
SpriteRenderer renderer;

renderer = gameObject.AddComponent<SpriteRenderer>();
SetHostVisibilityNetworkBehaviour comp = gameObject.AddComponent<SetHostVisibilityNetworkBehaviour>();
comp.OnSetHostVisibility(false);

Assert.That(comp.called, Is.EqualTo(1));
Assert.That(renderer.enabled, Is.False);
}
}
}
3 changes: 0 additions & 3 deletions Assets/Tests/Runtime/NetworkIdentityCallbackTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,6 @@ class RebuildEmptyObserversNetworkBehaviour : NetworkVisibility
{
public override bool OnCheckObserver(INetworkPlayer conn) { return true; }
public override void OnRebuildObservers(HashSet<INetworkPlayer> observers, bool initialize) { }
public override void OnSetHostVisibility(bool visible)
{
}
}


Expand Down

0 comments on commit df499ab

Please sign in to comment.