Skip to content

Commit

Permalink
feat: Network Scene Checker Component (#1271)
Browse files Browse the repository at this point in the history
* Create Network Scene Checker Component

* Move objects to subscene in client

* Remove OnStartClient

* Rewritten with static dictionary

* Updated doc

* renamed image

* Replaced image

* fixed image name

* Changed to short-circuit return in Update

* Changed to using string for key since additive scenes may be unloaded

* Added null check

* Removed commented line

* Update Assets/Mirror/Components/NetworkSceneChecker.cs

Co-Authored-By: vis2k <info@noobtuts.com>

* Moved initializer to declaration

* Removed [Scene, SerializeField]

Co-authored-by: vis2k <info@noobtuts.com>
  • Loading branch information
MrGadget and miwarnec committed Jan 25, 2020
1 parent 16b4818 commit 71c0d3b
Show file tree
Hide file tree
Showing 5 changed files with 144 additions and 0 deletions.
115 changes: 115 additions & 0 deletions Assets/Mirror/Components/NetworkSceneChecker.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
using UnityEngine;
using System.Collections.Generic;
using UnityEngine.SceneManagement;

namespace Mirror
{
/// <summary>
/// Component that controls visibility of networked objects between scenes.
/// <para>Any object with this component on it will only be visible to other objects in the same scene</para>
/// <para>This would be used when the server has multiple additive subscenes loaded to isolate players to their respective subscenes</para>
/// </summary>
[AddComponentMenu("Network/NetworkSceneChecker")]
[RequireComponent(typeof(NetworkIdentity))]
[HelpURL("https://mirror-networking.com/docs/Components/NetworkSceneChecker.html")]
public class NetworkSceneChecker : NetworkBehaviour
{
/// <summary>
/// Flag to force this object to be hidden from all observers.
/// <para>If this object is a player object, it will not be hidden for that client.</para>
/// </summary>
[Tooltip("Enable to force this object to be hidden from all observers.")]
public bool forceHidden;

static Dictionary<string, HashSet<NetworkIdentity>> sceneCheckerObjects = new Dictionary<string, HashSet<NetworkIdentity>>();

string currentScene;

[ServerCallback]
void Awake()
{
currentScene = gameObject.scene.name;
}

public override void OnStartServer()
{
if (!sceneCheckerObjects.ContainsKey(currentScene))
sceneCheckerObjects.Add(currentScene, new HashSet<NetworkIdentity>());

sceneCheckerObjects[currentScene].Add(netIdentity);
}

[ServerCallback]
void Update()
{
if (currentScene == gameObject.scene.name)
return;

// This object is in a new scene so observers in the prior scene
// and the new scene need to rebuild their respective observers lists.

// Remove this object from the hashset of the scene it just left
sceneCheckerObjects[currentScene].Remove(netIdentity);

// RebuildObservers of all NetworkIdentity's in the scene this object just left
RebuildSceneObservers();

// Set this to the new scene this object just entered
currentScene = gameObject.scene.name;

// Make sure this new scene is in the dictionary
if (!sceneCheckerObjects.ContainsKey(currentScene))
sceneCheckerObjects.Add(currentScene, new HashSet<NetworkIdentity>());

// Add this object to the hashset of the new scene
sceneCheckerObjects[currentScene].Add(netIdentity);

// RebuildObservers of all NetworkIdentity's in the scene this object just entered
RebuildSceneObservers();
}

void RebuildSceneObservers()
{
foreach (NetworkIdentity networkIdentity in sceneCheckerObjects[currentScene])
if (networkIdentity != null)
networkIdentity.RebuildObservers(false);
}

public override bool OnCheckObserver(NetworkConnection conn)
{
if (forceHidden)
return false;

return conn.identity.gameObject.scene == gameObject.scene;
}

// Always return true when overriding OnRebuildObservers so that
// Mirror knows not to use the built in rebuild method.
public override bool OnRebuildObservers(HashSet<NetworkConnection> observers, bool initialize)
{
// If forceHidden then return true without adding any observers.
if (forceHidden)
return true;

// Add everything in the hashset for this object's current scene
foreach (NetworkIdentity networkIdentity in sceneCheckerObjects[currentScene])
if (networkIdentity != null && networkIdentity.connectionToClient != null)
observers.Add(networkIdentity.connectionToClient);

return true;
}

/// <summary>
/// Called when hiding and showing objects on the host.
/// On regular clients, objects simply spawn/despawn.
/// On host, objects need to remain in scene because the host is also the server.
/// In that case, we simply hide/show meshes for the host player.
/// </summary>
/// <param name="visible"></param>
public override void OnSetHostVisibility(bool visible)
{
foreach (Renderer rend in GetComponentsInChildren<Renderer>())
rend.enabled = visible;
}
}
}
11 changes: 11 additions & 0 deletions Assets/Mirror/Components/NetworkSceneChecker.cs.meta

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

16 changes: 16 additions & 0 deletions doc/Components/NetworkSceneChecker.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# NetworkSceneChecker

The Network Scene Checker component controls the visibility of game objects for network clients, based on which scene they're in.

![Network Scene Checker component](NetworkSceneChecker.png)

- **Force Hidden**
Tick this checkbox to hide this object from all players.

With the Network Scene Checker, a game running on a client doesn’t have information about game objects that are not visible. This has two main benefits: it reduces the amount of data sent across the network, and it makes your game more secure against hacking.

This component would typically be used when the server has several subscenes loaded and needs to isolate networked objects to the subscene they're in.

A game object with a Network Scene Checker component must also have a Network Identity component. When you create a Network Scene Checker component on a game object, Mirror also creates a Network Identity component on that game object if it does not already have one.

Scene objects with a Network Scene Checker component are disabled when they're not in the same scene, and spawned objects are destroyed when they're not in the same scene.
Binary file added doc/Components/NetworkSceneChecker.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 2 additions & 0 deletions doc/Components/toc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
href: NetworkManagerHUD.md
- name: NetworkProximityChecker
href: NetworkProximityChecker.md
- name: NetworkSceneChecker
href: NetworkSceneChecker.md
- name: NetworkRoomManager
href: NetworkRoomManager.md
- name: NetworkRoomPlayer
Expand Down

0 comments on commit 71c0d3b

Please sign in to comment.