Hey folks,
I was hoping someone could give me a quick breakdown of what the process might be for unloading and clearing all resources associated with a scene so that I could load another one. Basically, much like levels, my game will have a scene the player is battling in and when that's finished, I'd like to unload everything and load up the next scene (or menu scene in this case).
I found a few functions that look appealing but I can't really tell what order I should be calling them and if there are any I'm missing. I expect to call...
m_Scene.Clear();
m_Scene.Dispose();
m_SceneInterface.Unload();
m_SceneInterface.Clear();
m_SceneEnvironment.Dispose();
I'm not sure what else I should call, and if I should even call those above. I'll be loading a new environment for the new scene as well so I do want to free the old before I load the next. I'll have a loading/transitional screen so wiping everything completely is fine (and probably desirable).
It looks like ::Dispose() is a virtual function that's a core piece of c#/xna, does that mark the object as garbage collectable? This is my first c#/xna/sunburn game so I'm just trying to wrap my head around all of these content managers and how best to encapsulate levels so I can manage everything a bit easier. I was thinking of having a second content manager for my menu (I'll be having a 3d scene for my frontend menu) and the first content manager for my in-game scenes and stuff...does that also make sense?
Sorry for such a beefy post, I guess this is a bit of an unknown area for me and I'd really like to set it all up as cleanly and flexible as possible.
Thanks for the help, much appreciated!
-Matt
Hi Matt,
I've seen the following used:
sceneInterface.LightManager.Clear();
sceneInterface.ObjectManager.Clear();
sceneInterface.LightManager.Submit(newScene);
sceneInterface.ObjectManager.Submit(newScene);
Sebastian
Sweet I'll give that a try, thanks for the help. :)
Sebastian, although this code is correct, I believe that there is a simpler way to accomplish this. Instead of explictly clearing each manager, I believe you can just clear and submit directly on the SceneInterface and it will iterate through all the registered managers and do what you need. This is functionally equivalent, but ultimately more robust and maintainable if you update/add new managers in the future your scene loading code will keep working. Hope that helps!
sceneInterface.Clear();
sceneInterface.Submit(scene);
Cool. So this takes care of relighting the new scene too?
Also could you do this to reset a level? I.e. after the player has been playing on some scene and then fail/die; can you just clear the scene and resubmit it for them to restart on?
~Sebastian
Hi DSebJ,
Scenes can only be relit at design time (either in the editor or in code), but yes clearing the scene interface and resubmitting a scene will automatically load the necessary light maps for you.
DSebJ:Also could you do this to reset a level?
That's an excellent question - normally this is how you'd expect it to work, however the content manager caches loaded assets, which means any changes you make will be reflected in the object next time you ask for it from the content manager.
Luckily there's an easy solution, just make sure to clone the scene after loading it and you'll always have a clean copy.
Let me know if this helps!
Follow me on Twitter – development and personal tweetsAwesome XNA Videos – Lighting, Rendering, and game videos
JohnK "bobthecbuilder":Luckily there's an easy solution, just make sure to clone the scene after loading it and you'll always have a clean copy.
Hi John,
Could you possibly expand on this a little please? I'm trying to reset the scene from within the editor (just using a key combo) by creating a clone when I load the scene but it doesn't seem to be working. I'm most likely doing something wrong.
When the scene loads I do this:
_sceneGenerator = new PrefabObjectGenerator(level.Scene);
When I reset the level I do this:
SceneInterface.Submit(_sceneGenerator.CreateObject<IScene>());
Not sure if I should do SceneInterface.Clear() first or not???
Thanks!
Ok, it seems I can't resubmit the scene from within the editor. It doesn't appear to do anything apart from briefly show a progress bar.
However, if I try to restart the scene outside of the editor I get weird results. I do the SceneInterface.Clear() followed by the Submit(<cloned scene>) but the scene objects don't appear in the right place for some reason (I need to double check it's not some of my code that's messing it up somewhere) and when I launch the editor I see multiple scenes (one being inactive).
:-S
I'll be having to write this same code in the next day or so... here's hoping you get it figured out so I can leverage your learnings. BTW, what is the exact code to clone a scene? Is that the PrefabGenerator call?
Hi holophone3D. I'm a bit baffled by this still.
As far as I can make out (from another similar post made a while back), the PrefabObjectGenerator should make a clone of the object/scene. Then you just call the CreateObject() method to get a copy of that clone. But I'm not certain about this. It could be that PrefabObjectGenerator merely holds a reference to the object to be cloned and then it creates a clone from that reference when calling CreateObject(). This would mean I'd get a clone of the current state of the scene, rather than the original state.
I really need John to clarify how it works.
Another consideration is, according to the API "objects can only be serialized in Windows", which makes sense, but then how do we use this to reset a level on the Xbox?
I'm getting a bit lost.
Anyone got any ideas?
Hi guys,
The prefab generator serializes any supported object types (eg: those that are serializable) to xml, which can be stored by your game for use in later sessions. Serialization is limited to Windows, however the xml can be deserialized on any platform.
Cloning as opposed to serializing is definitely a better and lighter weight option. I was under the impression the Scene class included a Clone() method, but it does not look like that's the case (I'll add this as a feature request).
However the contained groups and objects (entities and lights) do support cloning, so you could manually create a new scene and loop though the groups calling Group.Clone(), adding the returned new group to the new scene.
Please note SunBurn performs deep-cloning, so cloning a group will automatically clone all contained objects as well, so you never have to recursively clone - very cool! :)
Thanks John, that's cleared things up a bit in my head. I got the impression from another post that cloning was done via the prefab generator but I'll ignore that now and create a reset scene function using Group.Clone() as you suggest.
I guess that will solve the inability to reload a scene from within the editor as well.
Thanks once again John.... and err any news due of when the next update will be released? (I can't wait!)
;-)
Hi CJ,
I just posted a new blog - no eta at the moment, but lots of new features to show off. :)
John - I just wrote the code to do the entity and light group cloning and I'm seeing some interesting access violation exceptions (I'm running Indie btw). I can't dig in too much more because they are clearly internal calls that have been obfuscated.
ILightGroup Clone call:
{"Attempt to access the method failed: SynapseGaming.LightingSystem.Lights.BaseLight.set_WorldBoundingBox(Microsoft.Xna.Framework.BoundingBox)"}
IEntityGroup clone call:
{"Attempt to access the method failed: SynapseGaming.LightingSystem.Rendering.SceneObject.dv(System.Boolean)"}
Let me know what else you need to investigate...
Hi holophone3d,
I looking for threads about how to adding more scenes or game levels in SunBurn, but I have a lot of understanding.
Please, could you post a short sample about the skeleton of main events in a game and how to manage the challenge from a level to another?
Thank you very much
-Fabio