-
Notifications
You must be signed in to change notification settings - Fork 201
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
Feedback for docs/basics/scenemanagement/custom-management.md #1053
Comments
Sara on Discord asked me to elaborate a little more on this, so I made a little video where I try to explain where I'm coming from. As I also state in the video, I'm not interested help specifically to my game, it's the general "handling of in-scene NetworkObject/Prefabs in Custom Scenemanagement" that I'm after - and I think more than me can benefit from more information about that on the docs :) |
Just some more info, now that I was rereading the page again: https://docs-multiplayer.unity3d.com/netcode/current/basics/scenemanagement/custom-management/ The two links that looks interesting in relation to my challenges here, are both "dead". Just goes to a 404 page. |
@Laumania
However, watching your video makes me believe you might want to get a little fancier with your approach since I think the brick wall you are running up against is the fact that the prefabs you are spawning aren't in the list of prefabs...which makes both of the above approaches not very helpful. The small example I am working on for you leverages from the NetworkBehaviour.OnSynchronize method where the very basic concept is this:
Where you need to make sure your server and client have the GenericPrefab in their prefab list so that will always spawn no matter what. Then it is up to your implementation of the NetworkBehaviour.OnSynchronize Order of Operations
Below is just one potential approach and is really pseudo code to provide you with the fundamental concept of what you most likely would want to do.
So, the general idea is to use a "GenericPrefab" (or more than one depending upon what makes the most sense for your project) that will be configured by the server but is something that the client "already knows about" without having to know about any of the unique/specific attributes of the object itself. The unique information is sent by the server to the client using custom serialized data via the Will post the example I have been putting together...might be a few days but the above is the general direction I am using...so you might look at the above and see if that makes sense to you and if it does then possibly prototype an implementation more specific to your project. |
Thanks for the updated links 👌 About your generic approach - it's nice information and something I might need for something else, but don't think it's what I'm after here. So I'll try a bit simpler now :D
Actually I can count on all the prefabs being in the networkprefabs list on both host and client. What I'm essentially asking is: "How to do I make this work when I'm using custom scenemanagement?" I know how to make a prefab, it's the part that replaces the in-scene prefab, with a dynamically spawned instance of the same prefab that is "network enabled" so it's synced. :) |
@Laumania
Below you will find a small project, for reference purposes, that also provides you with a some in-scene placed parenting examples when scene management is disabled. With scene management disabled you have to handle parenting in-scene placed NetworkObjects yourself on the client side of things. The two examples I provided are in-scene placed NetworkObjects parented under:
The caveat to this is only if you have an in-scene placed NetworkObject parented under a dynamically spawned NetworkObject. Under this scenario, since both are dynamically spawned on the client side, the parenting should be handled for you. Here is the small example project for reference purposes: Why the multiple registrations?Since in-scene placed NetworkObjects are given unique GlobalObjectIdHash values (to distinguish them from other instances within the same scene) and since disabling scene management will make the server just simply provide the spawn information for all NetworkObjects as if they are dynamically spawned, you need to create the hash value override in order to provide the client with a "look up table" that links to the original network prefab. It isn't the greatest approach, but basically this is what scene management is handling internally (it builds its own version of a table to know "which in-scene placed NetworkObject" is being spawned). It is definitely an area we could improve upon, but that is basically "how to get clients spawning in-scene placed NetworkObjects" when scene management is disabled. Let me know if you have any more questions about this. Cheers! 👍 |
Ok, now we start talking - we are getting closer to what I'm after 👍. My problem is that I cannot do the above upfront in the editor, as I don't know these things ahead of time. So, simply put, how would you do what you just showed above, but in code? :) |
@Laumania
There are two areas of focus:
The second area of focus I think will be the more complicated aspect of this since you are having to reconstruct the mod's unique configurations. |
Now we are really talking! This looks very much like something I can use! 🤓 Really excited to give this a try - I'll try it out over the next few days and will get back. |
@Laumania |
@NoelStephensUnity Yeah I figured that. Right now I don't think I have a need to "sync" like that, as all is on the prefab itself and assume NetworkTransform, NetworkRigidbody and other NetworkVariables are synced out of the box as normally. I cannot make sure all is in the networkprefab list on the client prior to connection, because as you might remember from my video, the first thing that happens after the connection is done is that the host tells the client what mods to install and load and what scene to load. But lets see what issues I run into - as said will look into it during this week I hope. UPDATE (2023-06-15): Just wanted to let you know that I haven't forgot, just working on preparing something in my game for an event, so I will have to look into this a bit later. I will be back with an update when I have given this a try :) |
@NoelStephensUnity I have a little time to test this out, but haven't gotten it to work yet. But I need to try some more stuff. However, while I'm doing that, just a little question. As I understand it, as soon as a client connection is approved, it sends all the networkobject ids to sync. Client --> Attempt to connect --> Host So its there a way to kind of postphone that sync to happen somehow or am I approaching this wrongly? What I generally do right now to avoid stuff to be synced until client is ready is to have this (or a variation of this) on my NetworkObjects:
|
Finally I got back to look into this and have tried various things to make it work and I simply can't. So I have made a simple sample that I hope you could maybe make work, or send to someone in Unity that can show how this is done. Because it's not working even in this super simple sample. I made a little video too to show it: Thanks in advance. |
Could you maybe help out here, see my comment above - or is @NoelStephensUnity already on it? Thanks in advance. |
Any updates on this one? |
@Laumania Getting your ngo-inscene-networkobject-sample to workIn regards to getting your project to work, with custom scene management you need to create overrides for your in-scene placed NetworkObjects: This attached modified version of your repository (thank you for making that) gets your simple project working properly: Why do you need to do this?With custom scene management, all NetworkObject instances are treated as if they are dynamically spawned. Since each in-scene placed NetworkObject has a unique GlobalObjectIdHash, you need to create the override to link the instance to the original prefab instance in order for it be dynamically spawned. Each client will actually delete any in-scene prefab instance before processing the list of NetworkObjects to be spawned (to avoid duplication). Regarding GlobalObjectIdHash Generation & In-Scene Placed NetworkObjects:If you created your prefab and created in-scene placed prefab instances before adding a NetworkObject to the source prefab itself, then that would cause an issue with the generation of the GlobalObjectIdHash value for the in-scene placed NetworkObject. This issue is resolved in PR-2707. How the fix in PR-2707 works:If you already have a bunch of in-scene placed prefab instances in one or more scenes prior to wanting to make the prefab a "network prefab" (i.e. add a NetworkObject to it), then after adding the NetworkObject you can right click on the NetworkObject of the source prefab and select "Refresh In-Scene Prefab Instances" that will basically:
I tested this using NGO's test project that has quite a few scenes in it and it is a pretty fast process (takes like ~1 second on an average PC). How to avoid this issue until PR-2707 makes it into an updateIf you create the prefab and add a NetworkObject instance to it prior to making the in-scene placed NetworkObject, then the GlobalObjectIdHash value for the in-scene placed prefab instance will be correct for each instance. What I still have no good answer to:
Now, regarding the downloading of the mods... it depends on what is considered in-scene placed vs dynamically spawned. If a mod has existing prefab instances of a source prefab that is specific to the mod, then you would need to add prefab entries with hash overrides during runtime... but the unfortunate part of this is that adding a NetworkObject to a prefab or instance of a prefab during runtime will not generate a unique GlobalObjectIdHash value for that prefab since that needs to be done in edit mode. |
Thanks for getting back - I have updated my sample project with your changes and now it works out of the box for me too. So far so good. Now that the most basic version of this works - I will try and add another sample where I add these overrides dynamically, to get closer to the challenge I need to solve in my game. I'm aware of the GlobalObjectIdHash issue, or a variant of it as I already ran into that in the beginning when I started adding multiplayer. So I have am following the issue on github about it too - however - due to the other "in scene networkobject" issues I was facing, I put that aside and focused on the scenes coming in via mods, which was oddly enough easier to get working - as they didn't have in scene networkobjects :P About the last part of the downloading and loading of mods - lets not worry about that, because if I can get dynamic adding these overrides to work - then that isn't a problem as I already have that part working. I'll get back when I have something that works - or run my head against a wall :D |
Oh one more thing, that "NetworkManagerHelper" was actually only confusing, as it didn't add anything in relation to the issue - right? It was only to be able to start Host and Client - and you can really do that right from the NetworkManager in the editor. |
Ok @NoelStephensUnity As a test duplicated the in scene instance of the prefab. It got what looks to be a new unique GLobalHashId, so all looked good.
Pretty clear what the error is - however it doesn't really make sense that I cannot have more than one in scene networkobject og each prefab? That sounds pretty useless, so I'm sure I'm doing something wrong - but this just seemed so obvious to be able to do like this. |
@Laumania |
@NoelStephensUnity Ok, yeah because if you cannot have more than one, it doesnt make sense in a lot of scenarios :) |
@Laumania
Here are the NGO changes so far in the wip branch The current requirements for these changes are:
See if using those minor adjustments in that branch work out better for your project's needs? |
Ok I got your sample working - but only when I build like the client and run the host in the editor. Guess this "Parallel Sync" issue have fooled me up until now :( Must see if I can find a fix for that, as it makes a lot easier to test using Parallel Sync.
Update of the GlobalObjectHashId for existing prefabs that were placed in a scene prior to getting a NetworkObject component added to their prefab (which is the case for all my in-scene I assume) I can use the work around for now I guess, as it's a "one time thing" I assume.
For my game, it's ok to have in-scene prefabs instances added in the editor to a scene. So that's no problem.
That shouldn't be a problem as far as I see right now.
Just to be clear, you mean the "Original prefab" needs to be registered prior to dynamically adding the overrides for all the instances of that prefab in the scene - right? Thank you for your help so far! Much much appreciated! Next step for me is to see if I can make it work with Parallel Sync, to speed up things and then after do a simple sample in my own game to see it work there too 🤞 |
Ok I "kicked tires" on your latest sample here to attempt and figure out why it was not working in Parallel Sync - however as I see it, things go "wrong" before we even get to the Parallel Sync part. In "Editor mode" all seems linked up correctly. The instance in the scene have a reference to the prefab (I removed the [HideInInspector] to see this in the editor). In general all is fine at this point. Now lets enter Play Mode and nothing more. Not starting a host, not joining as client or anything. And right away I see a problem. The confusion is real :D PS: I pushed a version with your changes to here: https://github.com/Laumania/ngo-inscene-networkobject-sample/tree/dynamic-sample |
@Laumania Regarding Parrel Sync, you might try the Multiplayer Play Mode and see if you have better luck with that... Otherwise if that isn't an option...like you mentioned in your merge of the changes, if you build the client it will work just fine but if you try it in parrel sync it possibly fails (I am guessing GlobalObjectIdHash issue?), which would make sense...for kicks and giggles...try updating the OnValidate method to this:
See if that gets Parrel Sync to recognize the property update for the prefab instance? |
Ok fair enough, it needs to be hidden.
I can't use that as I'm sticking to LTS right now, which is 2022.x and that Multiplayer Play Mode is 2023.x only it seems. I tried something else...and even with the TargetPrefab being hidden and all as was in your sample, I still think it might be a "Unity/GlobalHash issue" at least I see this by just running the gam ein Play Mode. So, I'm debugging out the globalhash value, as at edit time I can clearly see they are not the same. However, as soon as I enter play mode - bum they are the same. So "something" happens. To my understanding, even in Editor these should continue to be different and if they were, I think this might actually work. I tried adding this too, as an attempt to try and avoid some validate/editor stuff - but same result: |
@Laumania What I noticed was missing in your repository's main branch:
From there, this is what I did:
You might try merging that PR and seeing if you have better luck? |
@NoelStephensUnity |
@Laumania |
@NoelStephensUnity Yeah "something" behaves differently in the Editor - but it's not a problem for the Host only the Client, why the client doesn't work running in Unity - which I think is also the reason Parallel Sync is not working (know you don't support it ;) ) |
@NoelStephensUnity As I wrote in the PR too, you missed the part where I wrote that all this "dynamic" stuff is pushed to another branch: https://github.com/Laumania/ngo-inscene-networkobject-sample/tree/dynamic-sample That version I have there works, but only if client is build and Editor is Host, but not the other way around as I also discovered. |
@Laumania Until I find another pocket of time to migrate the changes into the dynamic branch, take a look at the changes I made to the InSceneFireworkHandler. Since the "funky" issue seems to be editor specific, I went ahead and just stored the target prefab's GlobalObjectIdHash value (which is correct during OnValidate) and then within the Start method I just use the m_TargetGlobalObjectIdHash to find the GameObject of the already registered target network prefab and return the GameObject (Prefab). This works with both the client or host running in the editor. Some things you might want to think about when scene management is disabled:
|
@NoelStephensUnity Oh thats cool I'll take a look. Looking forward to try out your sample and poke around :) |
@NoelStephensUnity Thanks! Now it seems to work - and funny enough (as I said) its working in Parallel Sync now too :D I'll commit to my branch https://github.com/Laumania/ngo-inscene-networkobject-sample/tree/dynamic-sample I'll poke a bit more around and see if it holds up. Thank you very very much so far :) |
@Laumania (That PR will include a link to the documentation updates for custom scene management that will use bunch of the discovery in this thread as reference. Hopefully that will help any other users that want to handle scene management themselves.) |
@NoelStephensUnity No worries with the fix not being there in 1.7.0 - I can use your patched version while poking around with this in my actual game and I'm sure 1.8.0 will be out before I have something to show and test with players anyway. I'll get back if I run into issues related to this. However, as the original issue said, I really think you should add a sample like this to the documentation, so others have an easier change to figure it out without having to be in direct contact with you like I have been here :) |
Yep! That will be part of the updated documentation that provides:
Stuff like that... |
@Laumania |
@NoelStephensUnity Oh that's nice! Looking forward try it out when it's out :) |
@Laumania Using the same branch of PR-2710 unless you want to specify a unique network prefab for your in-scene placed fireworks, you no longer have to handle creating the overrides as this is now automatically handled for you when scene management is disabled. Of course, if you want to dynamically change the final prefab you could still use the same scripting approach in your InSceneFireworkHandler but as far as your sample project is setup it is no longer needed. To validate this with the way your project is currently setup and using the most recent updates to PR-2710 you should be able to:
Then take it for a spin. The client side should "automatically" know what source prefab asset it needs to spawn for each in-scene placed prefab instance. 👍 As well, you can also still register the same prefab with an actual override (for dynamic spawning) which will yield the following behavior:
I figured someone might want to still be able to have an in-scene placed instance of a prefab while also being able to dynamically spawn that same instance but with an override applied. Note: The one thing that is not supported by NGO when scene management is disabled is in-scene defined NetworkObject instances (i.e. not a network prefab instance). We might support that kind of functionality in the future, but there is a large chunk of code in NetworkSceneManager, when scene management is enabled, that handles synchronizing in-scene defined NetworkObjects and there are a lot of "opinionated" decisions that had to be made in order to get all of that working smoothly. The PR is pretty much finished other than the documentation updates I need to apply, but it should make it out into the next minor version update of NGO (i.e. v1.8.0). Let me know if you run into any issues with this update, but I think this should make life much easier for anyone wanting to handle scene synchronization themselves. |
@NoelStephensUnity THIS IS AWESOME! Can't wait to try it out :) I'll get back once I have tested it. |
This is the very best of open source developing out in the open. I really like the non-scene management solution above. Great job. |
I'm seeing in the NGO version drop down on the documentation page it goes up to v1.8.0, but I'm only seeing up to 1.7.1 available in package manager. I'm using Unity 2022.3.6f1 . |
Hey @NoelStephensUnity am I right in thinking we can close this issue now that changes to both docs and code have been delivered? |
@jabbacakes As the creator of this issue, I would say it sounds like you have done what I was asking - however I sadly haven't had the chance yet to try it out. Hopefully I will soon. If you could keep this open for a few weeks more I would be happy. |
Nah, if it's relevant to still keep it open, then we can ^_^ I'm just having a tidy up of old issues/PRs etc. in the repo. Let us know how you get on with the new features! |
@jabbacakes Cool! Yeah I'll for sure tag you, or simple just close the issue once I have tested the changes out. |
Hi @jabbacakes So I'm getting back to this and are looking into it. Upgraded to NGO 1.8.1 and I see a lot have changed and made things easier. Just dragging in a prefab (that have NetworkObject on it) and then load scene dynamically (custom scene management turned off) works fine - perfect! However, if you turn custom scene management off, you do it for a reason. In my case I load dynamic scenes(maps) via mods. Therefore, I would like to add all NetworkObject prefabs i can find in the scene, dynamically to the prefablist. In the documentation it says:
I would suggest you add a code sample, just to give programmers an idea what methods we are playing with here. What I'm doing now in my game is this, and it's now working:
Some code to help devs in the right direction would be awesome there :) |
@jabbacakes Ok we can close this now, as it seems to be working :) |
Thanks @Laumania. It's a pleasure to work with engaged community members like yourself. ^_^ |
Likewise it's a pleasure working with guys like you @jabbacakes and @NoelStephensUnity. |
When doing custom scene management, I assume (at least in my case), it's because you are already doing some more advanced/complex stuff. With that in mind, can you please add a more advanced sample or link to a github sample, of how to handle in-scene prefabs when scene management is turned off.
The sample you have, with copy GlobalObjectIdHash and paste into Network Prefabs, Im sure is fine. However, as mentioned, when you do more advanced stuff where thigns are loaded dynamically etc. this doesn't really fly.
So really I'm after some samples on how to get in-scene network prefab instances and setup via code so it have correct overrides to work on client etc.
https://docs-multiplayer.unity3d.com/netcode/current/basics/scenemanagement/custom-management/#building-your-own-scene-management-solution
The text was updated successfully, but these errors were encountered: