Skip to content
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

Networked Objects In Additive Scenes Not Enabled #72

Closed
MrGadget1024 opened this issue Oct 14, 2018 · 28 comments
Closed

Networked Objects In Additive Scenes Not Enabled #72

MrGadget1024 opened this issue Oct 14, 2018 · 28 comments
Labels
enhancement New feature or request

Comments

@MrGadget1024
Copy link
Collaborator

MrGadget1024 commented Oct 14, 2018

Describe the bug
When child scenes are loaded additive, objects with network identities don't appear in client or server.

Repro project
https://www.dropbox.com/s/orq17qrsug7hjsi/Test%20Mirror.zip?dl=0

To Reproduce
Steps to reproduce the behavior:

  1. Open the attached project.
  2. Run in Editor.
  3. Click Start as LAN Server Only.
  4. Observe child scenes loaded.
  5. Build to desktop and run the EXE as LAN Server Only.
  6. In Editor, Play as LAN Client.
  7. With WASD move the player to where ZoneA or ZoneB are located.
  8. Observe child scene(s) loaded.
  9. Observe child scene networked objects remain disabled.

Expected behavior
Child scene networked objects should be visible.

Desktop (please complete the following information):

Additional context
No warnings or errors in console or output_log.txt but debug msgs are logged as expected.

In the _Prefabs folder, find Cubes, Cylinders, and Spheres prefabs.
Remove the Network Identity components from Cylinders, and Spheres to see what it should look like.
The Cubes in ZoneC are not networked objects and they work correctly when ZoneC is entered / exited.

  • _Scripts/ServerStartup is what loads all child scenes on server when started.
  • _Scripts/ZoneHandler is attached to the 3 Zone prefabs (Server Only) and has OnTriggerEnter/Exit handlers.
  • _Scripts/SceneLoader is attached to the Player prefab and has the ClientRPC's to do the actual loading of child scenes.

If you do a build, make sure to include MainScene and SceneA, SceneB, and SceneC.

Find MrGadget in Discord if you need more info.

@miwarnec
Copy link
Collaborator

miwarnec commented Oct 21, 2018

Hi @MrGadget1024 , thanks for the report.
I do not recommend additive scene loading. UNET wasn't originally designed for it as it seems.
In fact, even regular scene loading didn't work properly until I fixed it a few months ago.

We might worry about additive scene loading in the future. But don't hold your breath, for now there is no easy way around regular scene loading, sorry.

@miwarnec miwarnec reopened this Oct 21, 2018
@miwarnec miwarnec added the enhancement New feature or request label Oct 21, 2018
@miwarnec miwarnec added bug Something isn't working and removed enhancement New feature or request labels Nov 9, 2018
@MrGadget1024
Copy link
Collaborator Author

To be clear, load additive isn't the problem, it's the conflicting ID's of the network objects across the various scenes.

@miwarnec
Copy link
Collaborator

miwarnec commented Nov 9, 2018

I changed it to 'bug' again.
There is a very easy fix to this, which is not starting sceneids at 0, but at sceneName.hash().
this sucks for bandwidth though, since for 0,1,2,3,4 etc. Mirror uses bytes automatically when sending.
for 21238567678+1+2+3 etc. it will need ints.

will think about a better way to do this

@MrGadget1024
Copy link
Collaborator Author

Can't network objects just have a ushort ID that has nothing to do with what scene they're in?

@miwarnec
Copy link
Collaborator

@MrGadget1024 can you please try this one: https://ci.appveyor.com/api/buildjobs/ar23p1ndj7wkp7u6/artifacts/Mirror%2FMirror.zip

DLLs are from this pull request:
#109

Seems to work fine for my test.

@MrGadget1024
Copy link
Collaborator Author

Tried latest, no joy. Uploaded test project to dropbox and updated link above.

@miwarnec
Copy link
Collaborator

@MrGadget1024 just checked it out, there is a lot of stuff in there. any chance you can reproduce it with a fresh project and just 2 scenes and 2 gameobjects etc.?

@MrGadget1024
Copy link
Collaborator Author

I've stripped the project down further, eliminating anything not necessary to the issue. The dropbox file linked in the original ticket above has been updated. I'm going to add more information to the ticket as well.

@miwarnec
Copy link
Collaborator

@MrGadget1024 Thanks, checking it out now.
I also just noticed that the title of this issues is 'not enabled..', I only worried about duplicate sceneids for some reason. Let's see..

@miwarnec
Copy link
Collaborator

ok just sharing my progress here for later:

  • NetworkServer.SetClientReadyInternal sends MsgType.SpawnFinished
  • which calls ClientScene.OnObjectSpawnFinished
  • which calls PrepareToSpawnSceneObjects
  • which populates ClientScene.s_spawnableObjects via FindObjectsOfTypeAll

If we do an additive scene load AFTER the client was set as ready then s_spawnableObjects won't know about any new scene objects that were in the extra loaded scene.

It also looks like FindObjectsOfTypeAll is called in several other places.

In other words: HLAPI was designed to find all scene objects on start, not every time. There is no immediate solution @MrGadget1024 , sorry. Perhaps load your objects from prefabs instead?

In the future we might detect additive scene loads and then add initialize everything in there again. This will require a lot of architecture changes and maybe break more other things. Hm.

@MrGadget1024
Copy link
Collaborator Author

Today's observations:

Sub-scene networked objects are present on client when additive scene loads but they're disabled and they all have netId = 0.

I tried adding Proximity Checker to the prefabs to see if that would wake them up but no joy.

@miwarnec
Copy link
Collaborator

Btw @paulpach looks like you came to the same conclusion in help channel (see my above post).
Another solution might be for netidentity.awake to add itself to the spawnable dictionary. this would avoid findobjectsoftype and would work for additive.

@miwarnec
Copy link
Collaborator

Trying this now. Looks like we need to do this in OnEnable/OnDisable because ClientScene.OnObjectDestroy disables and then removes it from dictionary (it doesn't destroy it)

@MrGadget1024
Copy link
Collaborator Author

Got a little closer. If, instead of adding the scenes to the server by code after start, I include them directly, everything on the server has proper sceneId's and netId's, and proximity messages are firing on the server.

@MrGadget1024
Copy link
Collaborator Author

I'm always in Discord and will try any builds you come up with.

@miwarnec
Copy link
Collaborator

@MrGadget1024 here is one version where they add themselves in OnDisable: #109

DLLs: https://ci.appveyor.com/api/buildjobs/6htybuojxat9gojb/artifacts/Mirror%2FMirror.zip

I need to get some sleep for now. This might work if you try it @MrGadget1024 , but we can't merge it yet because OnPostProcessScene -> setactive(false) -> ondisable -> spawnableObjects.add would add sceneids from objects that are not in the starter scene, which means that there would be problems if someone tries to spawn them even though the extra scene isn't loaded. or perhaps not. I need sleep :)

@miwarnec
Copy link
Collaborator

also @paulpach we might need to think about that whole sceneId magic from the ground up.
maybe netIds are enough. maybe there is a better way.

@kristianpd
Copy link

I tackled a similar issue with my stuff (though it may not work exactly with yours).

https://gist.github.com/kristianpd/485fd7d78512a22a80117a2d22664185

The meat of it is here:
https://gist.github.com/kristianpd/485fd7d78512a22a80117a2d22664185#file-basicnetworkedscenemanager-cs-L275

Where I basically just iterate over network identity's in the scene and force their sceneids to be a unique ID. The problem is that they share the same scene ids are another scene, starting over at 0. I guarantee uniqueness by simplify using the scene id (from build index) as an offset, and give each scene a range of valid integergers. Each scene gets a range of MAX_INT / Number of scenes sceneids. Does that make sense?

So networkidentity with sceneid 0 from Scene 1, would conflict with networkidentity with sceneid 2 from Scene 2.

This solution has a bit of custom messaging around it, but hopefully this helps provide some ideas?

I know @vis2k said one big problem was messages being sent before the scene is loaded. I did not encounter this (yet), but my test scene was fairly straightforward (2 sample scenes, a few network identities in each, loading / unloading asynchronously).

@paulpach
Copy link
Contributor

Here are my findings so far. The branch + this code fixes the issue, but it only seems to work in the editor:

 public override void OnStartServer()
    {
        base.OnStartServer();

        SceneManager.sceneLoaded += (Scene arg0, LoadSceneMode arg1) =>
            {
                NetworkServer.SpawnObjects();
            };

        Debug.Log("Loading Scenes");

        foreach (string SceneName in Scenes)
            StartCoroutine(LoadScenes(SceneName));
    }

Either the sceneLoaded event is not invoked in standalone, or it is invoked in the wrong order.

My next attempt is to add a non networked gameojbect to the child scenes that will call SpawnObjects(). This will always be executed when the child scene finishes loading and should register all the networked objects that got added.

@uweenukr
Copy link
Contributor

Would it help to manually manage the sceneId via either ForceId or adding another method to specify the desired sceneid during spawning?

Also is there a handy way to find out what the sceneId equates to at runtime?

@paulpach
Copy link
Contributor

paulpach commented Dec 26, 2018

@uweenukr the sceneid is already assigned correctly (in the branch). That is not the issue. The issue is that mirror does not recognize the newly added scene objects as such, so they are not spawned in the clients. Mirror searches for all scene objects when it starts and keeps them in a dictionary. We just need to tell it search again after the other scene loads

@uweenukr
Copy link
Contributor

Just to clarify. I'm getting to this error when spawning fails: "Spawn scene object not found for "

@uweenukr
Copy link
Contributor

Speaking of check for other objects to spawn. I also noticed when spawning fails I get this weird log entry from OnObjectSpawnFinished. It says SpawnFinished0 immediately followed by 1.

That seems to set off a chain of paused while loading msgs. The left side spawning works. The right side it fails.

https://imgur.com/a/Mi3ZyMW

@MrGadget1024
Copy link
Collaborator Author

Attached is a 2018 version of the repro project. The Library folder is left out so it's smaller...Unity will rebuild it. This is from Unity 2018.2.20

  • Open the MainScene only.
  • Build and run as LAN server...run in Editor as client.
  • WASD to move the player capsule around.
  • Objects with ProximityChecker appearing when they should not, e.g. the tall "buildings" around the perimeter appear randomly when player is far away
  • zone prefabs are appearing near the player (wrong place) but should never appear at all.
  • Random warnings and errors in console
    • OnTrigger* firing on Client on objects marked Server Only and with [Server] attribute
    • Spawn scene object not found for # error
  • Client eventually freezes up and no longer responds to WASD (HUD buttons still work)
  • Networked objects in additive loaded scenes aren't enabled when the scene is loaded or by proximity.

Test Mirror 2018.zip

image

@uweenukr
Copy link
Contributor

I dont know if the logging changed for the 2018 branch but this is much easier to follow:

screenshot

I now have a test scene that fails 100% of the time. Dont know if thats better or worse.

@MrGadget1024
Copy link
Collaborator Author

Latest repro made with 2018.2.20 (fixed wrongly commented lines)
Test Mirror 2017.zip

@paulpach
Copy link
Contributor

@MrGadget1024
Copy link
Collaborator Author

Confirmed fixed in #175
There are specific code requirements needed for implementation -- I'll document soon.

@paulpach paulpach added enhancement New feature or request and removed bug Something isn't working labels Jan 14, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

5 participants