-
Notifications
You must be signed in to change notification settings - Fork 450
Experimental/singleton removal merge #495
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
Conversation
…codegen but expect I'll need a bit of help to figure out what to do in NetworkBehaviourILPP
|
// TODO: put this back!!! | ||
/*namespace MLAPI.EditorTests |
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.
this is definitely not acceptable :)
I did this because I can no longer use var inReader = PooledBitReader.Get(inStream)
API
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.
I've fixed this is the new equivalent file (NetworkSerializerTests), although my solution requires a NetworkManager to be present in the test scene.
public void SetSingleton() | ||
{ | ||
Singleton = this; | ||
|
||
if (OnSingletonReady != null) | ||
OnSingletonReady(); | ||
OnSingletonReady?.Invoke(); |
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.
this function and OnSingletonReady
event should be gone, probably.
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.
yes, removed it.
{ | ||
using (PooledBitReader reader = PooledBitReader.Get(stream)) | ||
using (var reader = networkingManager.PooledBitReaders.GetReader(stream)) |
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.
I get the singleton-side change. But, out of curiosity, what's the rationale for using var
instead of the type ?
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.
It's kind of like the 'auto' specifier in C++.
/// </summary> | ||
public static NetworkingManager GetAnyNetworkingManager() | ||
{ | ||
return FindObjectOfType<NetworkingManager>(); |
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.
While I get this is just editor code FindObjectOfType
is one of the worst functions ever! Also assume we have more than one manager in a scene that has different settings does that matter ?
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.
We had similar discussions over at the RFC-side in case you'd like to contribute :)
if(NetworkingManager.Singleton != null && NetworkingManager.Singleton.IsServer) | ||
|
||
//FIXME: Singleton Conversion, get all of them and be sure to get the server! | ||
NetworkingManager manager = NetworkingManagerEditor.GetNetworkingManager(true); |
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.
So I think generally in the non-singleton case I would expect the editors to show only useful data if the actual object being selected is a NetworkManager... I just don't think that picking the first thing you see if actually useful.
Also FindObjectOfType doesn't guarantee order so you could call it more than once and get different objects which doesn't seem like the desired behavior either.
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.
This is probably the #1 unresolved issue in this addition
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.
I called out something similar on the RFC-side, inlining my suggestions here too:
Rather than finding
NetworkManager
withGameObject.FindWithTag
, it might be useful to have astatic NetworkManager[]
array globally where we could quickly iterate over and find the one we're looking for.
Similar to what I said above, we could store
NetworkManager
instances in astatic NetworkManager[]
container to avoidObject.FindObjectOfType
call.
(response to Matt's Dictionary idea)
oh, static array or hashmap, the main idea being avoiding gameobject hierarchy traversal withObject.FindObjectOfType
because seems like it could be unnecessary with a faster centralized static container lookup.
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.
Yeah, I think one way or another we'll want a central table of NMs
/// </summary> | ||
public NetworkingManager NetworkManager => NetworkingManager.Singleton; | ||
public NetworkingManager NetManager { get; internal set; } |
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.
Why did we change the name to NetManager ?
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.
yeah, we shouldn't change that like this — we're going to have a renaming RFC soon where we will specifically discuss naming types.
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.
these are all normalized to NetworkManager now.
return; | ||
} | ||
|
||
NetworkingManager networkingManager = networkedObjects[0].NetManager; |
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.
Is it guaranteed that every NetworkObject will have the same NetManager?
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.
@TwoTenPvP this (and the non-static NetworkShow) are not in use. Are these worth keeping around?
If so, we could make this an instance method off of NetworkedManager and if you pass in a NetworkedObject that doesn't belong to this NM, just skip it or throw an exception.
Or, it could be a static method off of NM. It really doesn't seem to have much to to with NetworkedObject. @wackoisgod not every NetworkObject has to have the same NM; but as written it would just show the pile of objects passed in regardless of NM.
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.
It was very difficult for me to envision a scenario where you would hand this method a heterogenous list of NetworkObjects, belonging to multiple different NetworkManagers. It seemed like something that could be handled by specifying that as a method precondition in the method's comments, which I've added in my latest changes.
That said, I was anticipating these methods would go away in favor of matt's new visibility work.
So I am concerned about that var name change from NetworkManager to NetManager on things as that is a breaking change |
container.ticks[i] = ProfilerTick.FromStream(stream); | ||
} | ||
{ | ||
container.ticks[i] = ProfilerTick.FromStream(manager, stream); |
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.
Same story here, in the FromStream lambda, you can first read the NM id, then de-ref and not need to pass this in.
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.
Also was able to break this dep same was as above
@@ -279,7 +282,7 @@ public void FromBase64(string base64) | |||
byte[] binary = Convert.FromBase64String(base64); | |||
using (BitStream stream = new BitStream(binary)) | |||
{ | |||
using (PooledBitReader reader = PooledBitReader.Get(stream)) | |||
using (PooledBitReader reader = NetManager.PooledBitReaders.GetReader(stream)) |
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.
How come this has to hang off of NetManager?
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.
Fixed to be a static again
@@ -334,12 +341,19 @@ public void NetworkHide(ulong clientId) | |||
/// <param name="clientId">The client to hide the objects from</param> | |||
public static void NetworkHide(List<NetworkedObject> networkedObjects, ulong clientId) | |||
{ | |||
if (!NetworkingManager.Singleton.IsServer) | |||
if( networkedObjects.Count == 0 ) |
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.
Same story as NetworkShow, above
{ | ||
throw new NotServerException("Only the server can perform lag compensation"); | ||
if( !simulatedObjects[0].NetObject.NetManager.IsServer ) |
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.
Oh boy, I guess you could however unlikely, have a collection of simulatedObjects were some are from one NM that is set up as a server and some are as a client. I haven't worked with LagCompensationManager though.
Is this telling us that this should be an instance method? There should be an LCM per NM?
{ | ||
if (!NetworkingManager.Singleton.IsServer) | ||
if (!networkingManager.IsServer) |
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.
Yeah, again, maybe this is telling us this should be an instance method.
@@ -10,69 +10,76 @@ | |||
|
|||
namespace MLAPI.Messaging | |||
{ | |||
internal static class InternalMessageSender | |||
internal class InternalMessageSender |
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.
We could leave this class static (and stateless) and just pass in NM in each send. What does the room think? That's more like what the UnnamedMessageSender does
/// <summary> | ||
/// The singleton instance of the NetworkingManager | ||
/// </summary> | ||
public static NetworkingManager Singleton { get; private set; } |
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.
I think we should get rid of this singleton boss but this PR looks like a mess to me.
(I know this is not a very constructive feedback, sorry).
There are lots of things going on here:
NetManager
/NetworkManager
,NetObject
and other naming inconsistencies- Assumptions like:
- Controversial changes like pinning
PooledBitReader
,InternalMessageSender
etc toNetworkManager
using (PooledBitReader reader = NetManager.PooledBitReaders.GetReader(stream))
- other fundamental behavioral changes which could be counted as high risks
Overall, I believe we need to redo/rework singleton removal again and think about design changes more carefully.
However, if I should consider this PR only as a draft that's never going to be merged into develop
, then I'm fine :)
This is a draft PR so we can have a place to discuss the singleton removal
I wanted to double-check the statement above.
{ | ||
#if DEVELOPMENT_BUILD || UNITY_EDITOR | ||
s_CleanBuffer.Begin(); | ||
#endif | ||
foreach (KeyValuePair<ulong, Queue<BufferedMessage>> pair in bufferQueues) | ||
{ | ||
while (pair.Value.Count > 0 && Time.realtimeSinceStartup - pair.Value.Peek().bufferTime >= NetworkingManager.Singleton.NetworkConfig.MessageBufferTimeout) | ||
while (pair.Value.Count > 0 && Time.realtimeSinceStartup - pair.Value.Peek().bufferTime >= messageBufferTimeout) |
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.
Do we think we want to have per-NM messageBufferTimeouts or could we simplify and have one shared static one?
@@ -30,45 +30,47 @@ public static class CustomMessagingManager | |||
/// </summary> | |||
public static event UnnamedMessageDelegate OnUnnamedMessage; | |||
|
|||
internal static void InvokeUnnamedMessage(ulong clientId, Stream stream) | |||
internal static void InvokeUnnamedMessage(NetworkingManager networkingManager, ulong clientId, Stream stream) |
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.
When I look at this function I really wonder what if we mad this an instance method off of NetworkingManager? It's weird to have a static method that takes an instance and then does most of its work with that instance.
com.unity.multiplayer.mlapi/Runtime/Messaging/RpcQueue/QueueHistoryFrame.cs
Outdated
Show resolved
Hide resolved
@@ -23,19 +23,25 @@ internal class RpcQueueProcessor | |||
// Batcher object used to manage the RPC batching on the send side | |||
private readonly RpcBatcher m_RpcBatcher = new RpcBatcher(); | |||
private const int k_BatchThreshold = 512; | |||
private NetworkingManager m_NetManager; |
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.
So it appears we have an NM instance in this class so that:
- we can get an NM-specific RPC Queue Container, which I have some doubts on is the right abstraction
- we can call NM:InvokeRPC (and, in turn, InvokeRPC is only in NM because it needs to find the right spawn manager, and maybe there's a cleaner way to do that)
- we can call NM:MessageSender.Send()
com.unity.multiplayer.mlapi/Runtime/NetworkedVar/Collections/NetworkedDictionary.cs
Outdated
Show resolved
Hide resolved
/// <param name="stream">The stream containing the ProfilerTick data</param> | ||
/// <returns>The ProfilerTick with data read from the stream</returns> | ||
public static ProfilerTick FromStream(Stream stream) | ||
public static ProfilerTick FromStream(NetworkingManager manager, Stream stream) |
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.
NM is being passed in so that ProfilerTickData can get an NM so that it can get a PooledBitReader, which - not to belabor the point - should be detached from NM
@@ -55,15 +55,19 @@ public class SceneSwitchProgress | |||
/// The callback invoked when a client is done loading the scene. | |||
/// </summary> | |||
public event OnClientLoadedSceneDelegate OnClientLoadedScene; | |||
|
|||
private NetworkingManager networkingManager; |
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.
inconsistent, is netManager everywhere else
|
||
NetworkEventType eventType = relayTransport.ReceiveFromHost(hostId, out int connectionId, out int channelId, messageBuffer, messageBuffer.Length, out int receivedSize, out byte error); | ||
|
||
if(eventType != NetworkEventType.Nothing ) |
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.
Did you mean to leave this in?
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.
Mostly want to have a discussion on where we can break the NetworkManager dependencies
com.unity.multiplayer.mlapi/Runtime/Messaging/RpcQueue/RpcQueueContainer.cs
Outdated
Show resolved
Hide resolved
@@ -186,9 +184,10 @@ public object ReadObjectPacked(Type type) | |||
{ | |||
ulong networkId = ReadUInt64Packed(); | |||
|
|||
if (networkingManager.SpawnManager.SpawnedObjects.ContainsKey(networkId)) | |||
var netManager = SpawnManager.SpawnedObjectsByNetworkingManager[networkId]; |
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.
After talking to @TwoTenPvP, I've come to see this is probably not correct code. Instead, I intend to remove this table and instead pass the NM into ReadObjectPacked.
{ | ||
foreach (var manager in FindObjectsOfType<NetworkingManager>()) | ||
{ | ||
if (manager.IsServer == isServer) |
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.
So I am confused by the IsServer check because from what I can tell its always false? https://github.com/Unity-Technologies/com.unity.multiplayer.mlapi/pull/495/files#diff-641f8f5b259017aefa68498910442cb599d894ed91c96e4811d0a79b5f0151feR24
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.
no, that's for the NetworkedObjectEditor.cs
in the Editor, not at Runtime I believe, no?
Just a heads up that I have updated this branch to fix all merge conflicts with develop. The branch is mergeable (at least as of this comment), but for some reasons, neither my latest changes, nor the merge status, is showing properly in this PR (maybe because this is Matt's PR, and it still represents the merge at the last commit that Matt made it?). |
Follow on note: I have finished an integration test against the BossRoom sample (which turned up a ton of problems!) I have fixed all of them, and I now think this PR could probably be taken (or rather a new one, from the latest commit on this branch). A couple of interesting things did change:
|
@mattwalsh-unity Can this be closed? |
@mattwalsh-unity can we close this? |
This is a draft PR so we can have a place to discuss the singleton removal