I want to initialise all my resources during my loading screen phase, so I thought I would wrap all my interactions with the asset manager inside a custom singleton.
My justification for this was that I could then ensure that all assets are loaded during the loading phase and if an asset was not loaded then it cannot be loaded at a later date by accident (of course you can just use the asset manager but I want to avoid this). Therefore I can easily see in my code if I have accidentally not loaded an asset during the loading phase because I will just throw a custom exception.
This all sounds pretty reasonable to me, so…
I went ahead and did this, storing all the objects from the asset manager locally in that class. all was great, until I realised that the Spatial was being shared between my entities… not good, they need one each.
I thought well maybe I could just load the mesh (but then I’d miss all the goodness of the loadModel method), then I thought maybe I could just clone the spatial every time I wanted to get a new one (I have a custom wrapper after all), then I thought maybe I should just use the asset manager (my wrapper looks to be becoming redundant).
So… what is the best way to achieve what I want from what I mention? Or maybe there is a better way?
At the moment I am leaning towards using my wrapper so that I can ensure that assets are loaded only during a loading phase, and I will load a spatial initially, and when I want to get it I will just clone it (meaning that the original spatial to be loaded will never actually be used, it will just be a blueprint which I clone from).
Really I’m just interested if anyone has any experience with this problem and what they do to sole it.
To effectively disable loading assets while keeping all other functionality the same, just unregister the ClasspathLocator. If any assets are uncached, AssetManager will attempt to locate the asset on disk which will fail because there are no locators.
I’m trying to say this as respectfully as possible… so please take it in the way its intended…
But if I understand you correctly, you’re coding all of this to avoid a relatively rare mistake (I hope) that is easily identified the first time you run it? And in this case the error state would be that your app still works and just slows down for a frame…
Seems like a lot of work to go through for relatively little gain.
Beware the trap of coding frameworks to no purpose. Our brains really like to do it because it’s safe and well-understood… but it doesn’t change the fact that it’s an opportunity for simple errors to slip in and ultimately it’s not even really needed.
Edit: also beware the trap of early optimization. If your game is running fine someday and you think “Man, where do these frame drops come from” then you’re already successful. Versus endlessly trying to micromanage some future issues and never getting to the ‘finish the game’ part.
I would then need to re-enable everything when I want to load more stuff this would be a pain in itself and and I believe that I have good reasons for wanting to to it my way, see below.
Not really, there are a variety of reasons.
to allow me to avoid errors
to allow me to handle assets in one central location rather than dotted throughout my code; lots of benefits here eg: I can easily load a game with a different texture set by passing one param into my Assets object (maybe I went from jungle to desert and now my men all wear desert camo instead of green!): I can quickly find and change materials of related types without having to do a search and replace etc… etc…
to allow me control of when assets are created, not just once but multiple times over and different asset types for different game modes (I might not have to load all the spaceship assets if I am starting out on the planet’s surface)
This is sound advice I appreciate it.
I am a sucker for optimising problems that aren’t actually problems, but…
…to me requires maintainable code And one of the things I strive to do for just this reason is separation of concerns (I might take it to extremes sometimes though).
I really appreciate the feedback guys. I think I will persist with my approach. I wrote the first draft in ~30 mins and it works and is pretty well… pretty It will need some work moving forwards but it isn’t a big task, I just wondered if someone knew of a really ingenious solution that I was completely unaware of. To be honest the AssetManager is still doing all the heavy lifting so I’m really grateful to have such a wonderful tool that has been created for us (jMonkeyEngine is awesome).
When the code is in a more stable state I’ll post it so you can see what I have done (if I remember and if it actually turns out not to be a complete lemon!)
I have a class called SmallGame which is defined as: “a game that loads all assets once and then only uses these assets”. It’s opposed to both LevelsGame and OpenWorldGame - LevelsGame has loading screens between GameLevel and OpenWorldGame uses a “streaming data” semantic.
The demonstration of my new framework is centered around that SmallGame which is demonstrated by a small atoll in the Pacific ocean where you can visit several small islands and all islands use the same trees, items, people and other assets.
My wrapper collects a Set<String> called ‘assetPaths’. All paths to all used assets must be in this Set. If a path is not in this Set, then you’ve encountered an error. To always reference at least one instance of each asset there is another Collection which is a List<CreditInfo> with CreditInfo being my struct for showing the asset in the game credits - currently I just show all assets sorted by their type - all models, all textures, all fonts, all sounds with their according meta info (models have different meta info than sounds, for example).
Originally I just went that road to show to new users of jME how to respect licenses by mentioning those assets in the credits of the game. Then I modified that thing a lot to include all kinds of meta info, which will be saved in a .meta file for every asset (at least, it can be done - and should be done). My credits now also support streaming only those assets that are currently depicted in the credits window versus just keeping a reference to one instance of each asset - which accomodates both OpenWorldGame and SmallGame with their respective requirements for asset streaming versus asset holding.
Well, hope it helps,
If you want to know more, you will have wait, because my framework will be out when some more time units have passed. But I think you get the big picture already…
Back in 2014 made something even more like what you want:
That game had all references referenced that the game would ever show.
If you know that your game will include exactly 20 bushes, 200 fruits, 12 quadrocopter drones, 8 monkeys, 8 drinks, 8 bowls, 8 forks, 8 spoons, 8 chairs, 4 tables - then you create those instances and set the CullHint of the Node to always cull after you’ve shown one frame with all visible.
This way you could be quite sure that your game either runs or doesn’t run - which I think is a question that game makers often fear (remember that flaw in “Planetary Annihilation” where the game simply crashes when you’ve played for a while).
The big problem is, that PC games don’t use dedicated hardware (in contrast to Console games). So you can never be sure and just need to tell your users “you should have … Gigabyte of RAM free when starting my game” - some less educated users might run several apps like Skype, Photoshop, some Youtube streams and other stuff and wonder why their game suddenly has extremely low frames per second ^^
… even consoles are not that reliable unfortunately, the RAM speed on the original Xbox was unique to each console as a result of shitty design and cost cutting… the same version of Halo could run on one console slower or faster than the next =/
In the past when I have such a finite level of optimisation, using Pools has solved majority of my issues, so I would say it’s at least worth looking into.