Experimental/singleton removal merge#495
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.
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.
I've fixed this is the new equivalent file (NetworkSerializerTests), although my solution requires a NetworkManager to be present in the test scene.
| NetworkConfig.NetManager = this; | ||
|
|
||
| rpcQueueContainer = new RpcQueueContainer(this, false, LoopbackEnabled); | ||
| rpcQueueContainer = new RpcQueueContainer(this, false); | ||
| //Note: Since frame history is not being used, this is set to 0 | ||
| //To test frame history, increase the number to (n) where n > 0 | ||
| rpcQueueContainer.Initialize(0); |
There was a problem hiding this comment.
this function and OnSingletonReady event should be gone, probably.
| List<INetworkedVar> networkedVarList, Stream stream, ulong clientId, NetworkedBehaviour logInstance) | ||
| { | ||
| using (PooledBitReader reader = PooledBitReader.Get(stream)) | ||
| using (var reader = networkingManager.PooledBitReaders.GetReader(stream)) |
There was a problem hiding this comment.
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.
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.
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.
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.
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.
This is probably the #1 unresolved issue in this addition
There was a problem hiding this comment.
I called out something similar on the RFC-side, inlining my suggestions here too:
Rather than finding
NetworkManagerwithGameObject.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
NetworkManagerinstances in astatic NetworkManager[]container to avoidObject.FindObjectOfTypecall.
(response to Matt's Dictionary idea)
oh, static array or hashmap, the main idea being avoiding gameobject hierarchy traversal withObject.FindObjectOfTypebecause seems like it could be unnecessary with a faster centralized static container lookup.
There was a problem hiding this comment.
Yeah, I think one way or another we'll want a central table of NMs
| /// The NetworkingManager that owns this Object. | ||
| /// </summary> | ||
| public NetworkingManager NetworkManager => NetworkingManager.Singleton; | ||
| public NetworkingManager NetManager { get; internal set; } |
There was a problem hiding this comment.
Why did we change the name to NetManager ?
There was a problem hiding this comment.
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.
these are all normalized to NetworkManager now.
| return; | ||
| } | ||
|
|
||
| NetworkingManager networkingManager = networkedObjects[0].NetManager; |
There was a problem hiding this comment.
Is it guaranteed that every NetworkObject will have the same NetManager?
There was a problem hiding this comment.
@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.
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.
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.
Also was able to break this dep same was as above
| 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.
How come this has to hang off of NetManager?
There was a problem hiding this comment.
Fixed to be a static again
| public static void NetworkHide(List<NetworkedObject> networkedObjects, ulong clientId) | ||
| { | ||
| if (!NetworkingManager.Singleton.IsServer) | ||
| if( networkedObjects.Count == 0 ) |
There was a problem hiding this comment.
Same story as NetworkShow, above
| if( simulatedObjects.Count > 0 ) | ||
| { | ||
| throw new NotServerException("Only the server can perform lag compensation"); | ||
| if( !simulatedObjects[0].NetObject.NetManager.IsServer ) |
There was a problem hiding this comment.
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?
| public static void Simulate(NetworkingManager networkingManager, ulong clientId, Action action) | ||
| { | ||
| if (!NetworkingManager.Singleton.IsServer) | ||
| if (!networkingManager.IsServer) |
There was a problem hiding this comment.
Yeah, again, maybe this is telling us this should be an instance method.
| namespace MLAPI.Messaging | ||
| { | ||
| internal static class InternalMessageSender | ||
| internal class InternalMessageSender |
There was a problem hiding this comment.
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.
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,NetObjectand other naming inconsistencies- Assumptions like:

- Controversial changes like pinning
PooledBitReader,InternalMessageSenderetc toNetworkManagerusing (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.
| 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.
Do we think we want to have per-NM messageBufferTimeouts or could we simplify and have one shared static one?
| 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.
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
| // 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.
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.
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
| /// </summary> | ||
| public event OnClientLoadedSceneDelegate OnClientLoadedScene; | ||
|
|
||
| private NetworkingManager networkingManager; |
There was a problem hiding this comment.
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.
Did you mean to leave this in?
mattwalsh-unity
left a comment
There was a problem hiding this comment.
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
| ulong networkId = ReadUInt64Packed(); | ||
|
|
||
| if (networkingManager.SpawnManager.SpawnedObjects.ContainsKey(networkId)) | ||
| var netManager = SpawnManager.SpawnedObjectsByNetworkingManager[networkId]; |
There was a problem hiding this comment.
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.
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.
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