Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
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
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ namespace Unity.Netcode
public class NetworkBehaviourUpdater
{
private HashSet<NetworkObject> m_Touched = new HashSet<NetworkObject>();
private HashSet<NetworkObject> m_TouchedThisClient = new HashSet<NetworkObject>();

#if DEVELOPMENT_BUILD || UNITY_EDITOR
private ProfilerMarker m_NetworkBehaviourUpdate = new ProfilerMarker($"{nameof(NetworkBehaviour)}.{nameof(NetworkBehaviourUpdate)}");
Expand All @@ -23,10 +24,12 @@ internal void NetworkBehaviourUpdate(NetworkManager networkManager)
m_Touched.Clear();
for (int i = 0; i < networkManager.ConnectedClientsList.Count; i++)
{
m_TouchedThisClient.Clear();
var client = networkManager.ConnectedClientsList[i];
var spawnedObjs = networkManager.SpawnManager.SpawnedObjectsList;
m_Touched.UnionWith(spawnedObjs);
foreach (var sobj in spawnedObjs)
networkManager.InterestManager.QueryFor(client, m_TouchedThisClient);

m_Touched.UnionWith(m_TouchedThisClient);
foreach (var sobj in m_TouchedThisClient)
{
// Sync just the variables for just the objects this client sees
for (int k = 0; k < sobj.ChildNetworkBehaviours.Count; k++)
Expand Down
14 changes: 13 additions & 1 deletion com.unity.netcode.gameobjects/Runtime/Core/NetworkManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using Unity.Netcode.Interest;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Weren't we shying away from sub-namespaces?

using UnityEngine;
using Unity.Profiling;
using Debug = UnityEngine.Debug;
Expand Down Expand Up @@ -39,7 +40,7 @@ public class NetworkManager : MonoBehaviour, INetworkUpdateSystem

internal MessageQueueContainer MessageQueueContainer { get; private set; }


internal InterestManager InterestManager { get; private set; }
internal SnapshotSystem SnapshotSystem { get; private set; }
internal NetworkBehaviourUpdater BehaviourUpdater { get; private set; }

Expand Down Expand Up @@ -244,6 +245,10 @@ internal void InvokeConnectionApproval(byte[] payload, ulong clientId, Connectio

internal static event Action OnSingletonReady;

// the interest settings objects receive unless they have a pre-prefab override
public InterestSettings InterestSettings;


#if UNITY_EDITOR
private void OnValidate()
{
Expand Down Expand Up @@ -439,6 +444,7 @@ private void Initialize(bool server)
MessageQueueContainer.Dispose();
MessageQueueContainer = null;
}
InterestManager = new InterestManager();

// The MessageQueueContainer must be initialized within the Init method ONLY
// It should ONLY be shutdown and destroyed in the Shutdown method (other than just above)
Expand Down Expand Up @@ -878,6 +884,12 @@ public void Shutdown()
NetworkTickSystem = null;
}

if (InterestManager != null)
{
InterestManager.Dispose();
InterestManager = null;
}

IsListening = false;
IsServer = false;
IsClient = false;
Expand Down
36 changes: 36 additions & 0 deletions com.unity.netcode.gameobjects/Runtime/Core/NetworkObject.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
using System.IO;
using System.Linq;
using System.Runtime.CompilerServices;
using Unity.Netcode.Interest;

using UnityEngine;

namespace Unity.Netcode
Expand All @@ -12,8 +14,11 @@ namespace Unity.Netcode
/// </summary>
[AddComponentMenu("Netcode/" + nameof(NetworkObject), -99)]
[DisallowMultipleComponent]

public sealed class NetworkObject : MonoBehaviour
{
public List<InterestNode> InterestNodes = new List<InterestNode>();

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did you intend for this to show up in the inspector? Is this configuration or state? If it's state, should apply [NonSerialized] so that it doesn't appear in inspector or impact the serialized size of network object components


[HideInInspector]
[SerializeField]
internal uint GlobalObjectIdHash;
Expand Down Expand Up @@ -177,6 +182,26 @@ internal set
/// </summary>
public bool AutoObjectParentSync = true;

public InterestSettings InterestSettingsOverride;
public InterestSettings InterestSettings
Comment on lines +185 to +186

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

From an API design perspective, you have redundant setters here. I think it would be better if you had a GetInterestSettings() method to replace InterestSettings, or alternatively a SetInterestSettingsOverride method and make InterestSettingsOverride private.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's a decent amount of code to expose a global InterestSettings asset, and per-object overrides, but InterestSettings currently has no actual content. Is there already a plan for how this will be used?

{
get
{
InterestSettings result = null;
if (InterestSettingsOverride)
{
result = InterestSettingsOverride;
}
else if (NetworkManager.InterestSettings)
{
result = NetworkManager.InterestSettings;
}

return result;
}
set => InterestSettingsOverride = value;
}

internal readonly HashSet<ulong> Observers = new HashSet<ulong>();

/// <summary>
Expand All @@ -193,6 +218,7 @@ public HashSet<ulong>.Enumerator GetObservers()
return Observers.GetEnumerator();
}


/// <summary>
/// Whether or not this object is visible to a specific client
/// </summary>
Expand Down Expand Up @@ -1072,5 +1098,15 @@ internal uint HostCheckForGlobalObjectIdHashOverride()

return GlobalObjectIdHash;
}

// Trigger the Interest system to do an update sweep on any Interest nodes
// I am associated with
public void UpdateInterest()
{
foreach (var node in InterestNodes)
{
node?.UpdateObject(this);
}
}
}
}
8 changes: 8 additions & 0 deletions com.unity.netcode.gameobjects/Runtime/Interest.meta

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

Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
using System.Collections.Generic;
using Unity.Netcode.Interest;
using UnityEngine;

namespace Unity.Netcode
{
// interest *system* instead of interest node ?
public class InterestManager
{
private readonly InterestNodeStatic m_DefaultInterestNode;

public InterestManager()
{
m_ChildNodes = new HashSet<InterestNode>();

// This is the node objects will be added to if no replication group is
// specified, which means they always get replicated
m_DefaultInterestNode = ScriptableObject.CreateInstance<InterestNodeStatic>();
m_ChildNodes.Add(m_DefaultInterestNode);
}

public void AddObject(in NetworkObject obj)
{
var nodes = obj.InterestNodes;

// If this new object has no associated Interest Nodes, then we put it in the
// default node, which all clients will then get.
//
// That is, if you don't opt into the system behavior is the same as before
// the Interest system was added
if (nodes.Count == 0)
{
m_DefaultInterestNode.AddObject(obj);
}
// else add myself to whatever Interest Nodes I am associated with
else
{
// I am walking through each of the interest nodes that this object has
// I should probably optimize for this later vs. doing this for every add!
foreach (var node in nodes)
{
// cover the case with an empty list entry
if (node != null)
{
// the Interest Manager lazily adds nodes to itself when it sees
// new nodes that associate with the objects being added
m_ChildNodes.Add(node);
// tell this node to add this object to itself
node.AddObject(obj);
}
}
}
}

public void RemoveObject(in NetworkObject oldObject)
{
var nodes = oldObject.InterestNodes;

// if the node never had an InterestNode, then it was using the default
// interest node
if (nodes.Count == 0)
{
m_DefaultInterestNode.RemoveObject(oldObject);
}
else
{
foreach (var node in nodes)
{
if (node == null)
{
continue;
}
node.RemoveObject(oldObject);
}
}
}

public void QueryFor(in NetworkClient client, HashSet<NetworkObject> results)
{
foreach (var c in m_ChildNodes)
{
c.QueryFor(client, results);
}
}

public void Dispose()
{
}

private HashSet<InterestNode> m_ChildNodes;
}
}

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

19 changes: 19 additions & 0 deletions com.unity.netcode.gameobjects/Runtime/Interest/InterestNode.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
using System.Collections.Generic;
using Unity.Netcode;
using UnityEngine;

namespace Unity.Netcode.Interest
{
public abstract class InterestNode : ScriptableObject
{
public abstract void QueryFor(in NetworkClient client, HashSet<NetworkObject> results);
public abstract void AddObject(in NetworkObject obj);
public abstract void RemoveObject(in NetworkObject obj);
public abstract void UpdateObject(in NetworkObject obj);
};

public abstract class InterestKernel : ScriptableObject

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this be in its own file?

{
public abstract void QueryFor(in NetworkClient client, in NetworkObject obj, HashSet<NetworkObject> results);
}
}

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

Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
using System.Collections.Generic;
using Unity.Netcode;
using UnityEngine;

namespace Unity.Netcode.Interest
{
[CreateAssetMenu(fileName = "StaticInterestNode", menuName = "Interest/Nodes/Static", order = 1)]

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since this menu item is applied to the Assets menu, Interest/Nodes/Static seems awkward from a user experience perspective. I would expect something like Netcode/Interest/Static Interest Node

public class InterestNodeStatic : InterestNode
Comment on lines +7 to +8

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Interesting that the file name and the class differ. Personally would recommend this should be called StaticInterestNode (most-specific-first naming)

{
public List<InterestKernel> InterestKernels = new List<InterestKernel>();

// these are the objects under my purview
protected HashSet<NetworkObject> ManagedObjects;

public void OnEnable()
{
ManagedObjects = new HashSet<NetworkObject>();
}

public override void AddObject(in NetworkObject obj)
{
ManagedObjects.Add(obj);
}

public override void RemoveObject(in NetworkObject obj)
{
ManagedObjects.Remove(obj);
}

public override void QueryFor(in NetworkClient client, HashSet<NetworkObject> results)
{
if (InterestKernels.Count > 0)
{
foreach (var obj in ManagedObjects)
{
foreach (var ik in InterestKernels)
{
ik.QueryFor(client, obj, results);
}
}
}
else
{
results.UnionWith(ManagedObjects);
}
}

public override void UpdateObject(in NetworkObject obj)
{
}
}
}

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

Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

namespace Unity.Netcode.Interest
{
[CreateAssetMenu(fileName = "ReplicationSettings", menuName = "Interest/Settings/InterestSettings", order = 1)]

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ReplicationSettings vs InterestSettings?


// these are settings used by the Interest management system to
// - adjust how it decides whether an item is replicated
// - adjust how prioritization occurs
public class InterestSettings : ScriptableObject
{
// TBD - add default interest settings here
}
}

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

Loading