-
Notifications
You must be signed in to change notification settings - Fork 459
feat: AOI interface #833
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
feat: AOI interface #833
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -3,6 +3,8 @@ | |
| using System.IO; | ||
| using System.Linq; | ||
| using System.Runtime.CompilerServices; | ||
| using Unity.Netcode.Interest; | ||
|
|
||
| using UnityEngine; | ||
|
|
||
| namespace Unity.Netcode | ||
|
|
@@ -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>(); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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; | ||
|
|
@@ -177,6 +182,26 @@ internal set | |
| /// </summary> | ||
| public bool AutoObjectParentSync = true; | ||
|
|
||
| public InterestSettings InterestSettingsOverride; | ||
| public InterestSettings InterestSettings | ||
|
Comment on lines
+185
to
+186
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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> | ||
|
|
@@ -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> | ||
|
|
@@ -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); | ||
| } | ||
| } | ||
| } | ||
| } | ||
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.
| 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 | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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)] | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Since this menu item is applied to the Assets menu, |
||
| public class InterestNodeStatic : InterestNode | ||
|
Comment on lines
+7
to
+8
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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)] | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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.
There was a problem hiding this comment.
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?