Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
cc36ca1
feat: Interest system [MTT-239]
mattwalsh-unity Apr 30, 2021
aaa0c91
fixups, #ifdef
mattwalsh-unity Oct 22, 2021
6d89ca5
template
mattwalsh-unity Jul 20, 2021
79567da
not screwed up now
mattwalsh-unity Oct 23, 2021
2484a7e
make interface, not abstract class
mattwalsh-unity Oct 26, 2021
961339d
checkpoint
mattwalsh-unity Oct 27, 2021
bb6bc00
new registration thing working
mattwalsh-unity Oct 27, 2021
67106a1
different registration
mattwalsh-unity Oct 29, 2021
bb4a6ff
refactor checkpoint
mattwalsh-unity Nov 3, 2021
6a3dd26
simplification
mattwalsh-unity Nov 3, 2021
3a7f24b
more cleanup
mattwalsh-unity Nov 3, 2021
63683cd
missed cleanup
mattwalsh-unity Nov 3, 2021
86a44f0
bug
mattwalsh-unity Nov 3, 2021
143c067
refactor node stuff
mattwalsh-unity Nov 4, 2021
dcb68a0
lint fixes
mattwalsh-unity Nov 4, 2021
d29cc19
Merge branch 'develop' into feature/interest-system
mattwalsh-unity Nov 4, 2021
19aecd4
backed out linq trap
mattwalsh-unity Nov 4, 2021
0c221ba
Merge branch 'develop' into feature/interest-system
mattwalsh-unity Nov 5, 2021
65b58f3
Merge branch 'develop' into feature/interest-system
andrews-unity Nov 8, 2021
d7bb5fa
Merge branch 'develop' into feature/interest-system
andrews-unity Nov 8, 2021
70af4cc
Merge develop into feature/interest-system
github-actions[bot] Nov 10, 2021
cf02c95
Merge branch 'develop' into feature/interest-system
andrews-unity Nov 10, 2021
b9bb5ba
Merge branch 'develop' into feature/interest-system
andrews-unity Nov 10, 2021
27f02bd
Merge branch 'develop' into feature/interest-system
andrews-unity Nov 10, 2021
2cdbe0f
cleanup, more ref's
mattwalsh-unity Nov 13, 2021
86adb19
Merge branch 'feature/interest-system' of github.com:Unity-Technologi…
mattwalsh-unity Nov 13, 2021
ca0aba1
Merge branch 'develop' into feature/interest-system
mattwalsh-unity Nov 13, 2021
c1976d6
interest cp
mattwalsh-unity Nov 16, 2021
1050c29
Merge branch 'develop' into feature/interest-system
mattwalsh-unity Nov 24, 2021
da48bab
remove interest settings (for now)
mattwalsh-unity Nov 24, 2021
422d73d
add kernels behind call
mattwalsh-unity Nov 24, 2021
c517d2c
negative results
mattwalsh-unity Nov 25, 2021
311ca34
improved QueryFor in kernels to be true/false
mattwalsh-unity Dec 2, 2021
e797a38
small fix, comments
mattwalsh-unity Dec 2, 2021
ed6a847
Merge branch 'develop' into feature/interest-system
mattwalsh-unity Dec 2, 2021
0c0a53e
lint updates
mattwalsh-unity Dec 2, 2021
ae6030a
Merge branch 'feature/interest-system' of github.com:Unity-Technologi…
mattwalsh-unity Dec 2, 2021
a6b7a5c
lint complaints, reverted to explicit new syntax
mattwalsh-unity Dec 2, 2021
3e4cc99
lint new() revert pt 2
mattwalsh-unity Dec 2, 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
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ public class NetworkBehaviourUpdater
{
private HashSet<NetworkObject> m_Touched = new HashSet<NetworkObject>();

// reused each call to NetworkBehaviourUpdate to avoid GC.
// should investigate using a native container
private HashSet<NetworkObject> m_InterestUpdateThisFrame = new HashSet<NetworkObject>();

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

m_InterestUpdateThisFrame.Clear();
networkManager.InterestManager.QueryFor(ref client.PlayerObject, ref m_InterestUpdateThisFrame);
foreach (var sobj in m_InterestUpdateThisFrame)

{
if (sobj.IsNetworkVisibleTo(client.ClientId))
{
m_Touched.Add(sobj);
// Sync just the variables for just the objects this client sees
for (int k = 0; k < sobj.ChildNetworkBehaviours.Count; k++)
{
Expand Down
22 changes: 22 additions & 0 deletions com.unity.netcode.gameobjects/Runtime/Core/NetworkManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
using System.Collections.Generic;
using Unity.Collections;
using Unity.Collections.LowLevel.Unsafe;
using Unity.Netcode.Interest;
using UnityEngine;
#if UNITY_EDITOR
using UnityEditor;
Expand Down Expand Up @@ -53,13 +54,29 @@ internal static string PrefabDebugHelper(NetworkPrefab networkPrefab)
return $"{nameof(NetworkPrefab)} \"{networkPrefab.Prefab.gameObject.name}\"";
}

private InterestManager<NetworkObject> m_InterestManager;

// For unit (vs. integration) testing and for better decoupling, we don't want to have to require Initialize()
// to use the InterestManager
internal InterestManager<NetworkObject> InterestManager
{
get
{
if (m_InterestManager == null)
{
m_InterestManager = new InterestManager<NetworkObject>();
}
return m_InterestManager;
}
}
internal SnapshotSystem SnapshotSystem { get; private set; }
internal NetworkBehaviourUpdater BehaviourUpdater { get; private set; }

internal MessagingSystem MessagingSystem { get; private set; }

private NetworkPrefabHandler m_PrefabHandler;


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.

Is this needed ?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

As in, do we need the getter? I ran into problems with testing and this lazy initialization scheme was my solution. I actually am not a fan on how all the other services above (e.g. NetworkBehaviourUpdater) don't initialize until NetworkManager::Initialize() is called and am interested in porting them to this way, because that means to exercise them I must call StartServer / StartHost, and maybe I don't want to require a stood-up, connected NM to test / exercise it.

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.

I mean the extra space :P

public NetworkPrefabHandler PrefabHandler
{
get
Expand Down Expand Up @@ -1099,6 +1116,11 @@ internal void ShutdownInternal()
NetworkTickSystem = null;
}

if (m_InterestManager != null)
{
m_InterestManager = null;
}

if (MessagingSystem != null)
{
MessagingSystem.Dispose();
Expand Down
32 changes: 31 additions & 1 deletion com.unity.netcode.gameobjects/Runtime/Core/NetworkObject.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
using System;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
using Unity.Netcode.Interest;

using UnityEngine;

namespace Unity.Netcode
Expand All @@ -10,12 +12,38 @@ namespace Unity.Netcode
/// </summary>
[AddComponentMenu("Netcode/" + nameof(NetworkObject), -99)]
[DisallowMultipleComponent]
public sealed class NetworkObject : MonoBehaviour

public sealed class NetworkObject : MonoBehaviour, IInterestObject<NetworkObject>
{
[HideInInspector]
[SerializeField]
internal uint GlobalObjectIdHash;

private List<IInterestNode<NetworkObject>> m_InterestNodes = new List<IInterestNode<NetworkObject>>();

public void AddInterestNode(IInterestNode<NetworkObject> node)
{
if (!m_InterestNodes.Contains(node))
{
node.AddObject(this);
m_InterestNodes.Add(node);
}
}

public void RemoveInterestNode(IInterestNode<NetworkObject> node)
{
if (m_InterestNodes.Contains(node))
{
node.RemoveObject(this);
m_InterestNodes.Remove(node);
}
}

public List<IInterestNode<NetworkObject>> GetInterestNodes()
{
return m_InterestNodes;
}

#if UNITY_EDITOR
private void OnValidate()
{
Expand Down Expand Up @@ -193,6 +221,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 @@ -1155,5 +1184,6 @@ internal uint HostCheckForGlobalObjectIdHashOverride()

return GlobalObjectIdHash;
}

}
}
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,13 @@
using Unity.Netcode.Interest;

namespace Unity.Netcode
{
public class AddAllInterestKernel : IInterestKernel<NetworkObject>
{

public bool QueryFor(NetworkObject clientNetworkObject, NetworkObject obj)
{
return true;
}
}
}

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,89 @@
using System.Collections.Generic;
namespace Unity.Netcode.Interest
{
internal interface IInterestObject<TObject>
{
public void AddInterestNode(IInterestNode<TObject> obj);
public void RemoveInterestNode(IInterestNode<TObject> obj);
public List<IInterestNode<TObject>> GetInterestNodes();
}

// interest *system* instead of interest node ?
internal class InterestManager<TObject> where TObject : IInterestObject<TObject>
{
private readonly InterestNodeStatic<TObject> m_DefaultInterestNode = new InterestNodeStatic<TObject>();

// Trigger the Interest system to do an update sweep on any Interest nodes
// I am associated with
public void UpdateObject(ref TObject obj)
{
List<IInterestNode<TObject>> nodes = obj.GetInterestNodes();
foreach (var node in nodes)
{
node.UpdateObject(obj);
}
}

public InterestManager()
{
// This is the node objects will be added to if no replication group is
// specified, which means they always get replicated
m_ChildNodes = new HashSet<IInterestNode<TObject>> { m_DefaultInterestNode };
}

public void AddObject(ref TObject obj)
{
// 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

List<IInterestNode<TObject>> nodes = obj.GetInterestNodes();

if (nodes.Count > 0)
{
// I am walking through each of the interest nodes that this object has
foreach (var node in nodes)
{
// the Interest Manager lazily adds nodes to itself when it sees
// new nodes that associate with the objects being added
m_ChildNodes.Add(node);
}
}
else
{
// if the object doesn't have any nodes, we assign it to the default node
AddDefaultInterestNode(obj);
}
}

public void AddDefaultInterestNode(TObject obj)
{
obj.AddInterestNode(m_DefaultInterestNode);
}

public void RemoveObject(ref TObject obj)
{
List<IInterestNode<TObject>> nodes = obj.GetInterestNodes();
foreach (var node in nodes)
{
if (node == null)
{
continue;
}
node.RemoveObject(obj);
}
}

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

private HashSet<IInterestNode<TObject>> 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;

namespace Unity.Netcode.Interest
{
public interface IInterestNode<TObject>
{
public void QueryFor(TObject client, HashSet<TObject> results);
public void AddObject(TObject obj);
public void RemoveObject(TObject obj);
public void UpdateObject(TObject obj);
public void AddAdditiveKernel(IInterestKernel<TObject> kernel);
public void AddSubtractiveKernel(IInterestKernel<TObject> kernel);
};

public interface IInterestKernel<TObject>
{
public bool QueryFor(TObject client, TObject obj);
}
}

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

Loading