A More Generic way of retrieving resources

I want to share my imperfect solution that allowed me to defer adoption of addressables and cloud based asset retrieval (for the time being). Long term the below isn’t all that great, but a lot of the stuff is reusable and/or was great learning.

  1. Set import settings for all images to power-of-two (POT) textures. This meant stretching them. You get the benefit of good cross-platform compression algorithms when textures are POT. Cross-platform (ios app, android app, desktop WebGL, mobile WebGL) is key for me. In my case, stretching then compressing the texture actually resulted in a smaller size file in almost all cases. Another advantage for me is that this makes the same asset available for both in game textures and UI (read on).
    If you go this route, you need is a “wrapper” around each stretched image file (I used an SO) that can save what the original dimension or aspect ratio was. In my case I need to store metadata with most of my images anyway this really was not a burden. It may be a terrible option for others so proceed with caution!
    Another option:
    I also considered using SVGs but that would have added some complexity I didn’t want to approach.
    Another option:
    Texture atlases. But also would have added some complexity I didn’t want to touch.

  2. To show textures in UI, I used a Raw Image component paired with an Aspect Ratio Fitter (vs trying to generate a Sprite for an Image component vs using “sprite” as my import setting). It meant a lot of refactoring, but in the end this actually simplified A LOT–that’s because I was already making heavy use of RenderTextures and need to support Sprites and RawImages anyway. This allowed me to simplify down to just RawImages.

  3. This refactoring also made it easy to create rudimentary support for asynchronously loaded assets. (e.g. stuff over the cloud). As mentioned, I sometimes use RenderTextures. In some cases, what I really needed was an animation/video and not a still. Instead of storing a pre-recorded video / instead of storing lots of stills I can dynamically generate certain types of content as needed.

  4. This refactoring highlighted some memory leaks associated with dynamically creating sprites from textures. No longer an issue because I use textures end-to-end. I also got experience using the memory profiler. Hooray!

Hacky? Maybe. :slight_smile: But I have bigger fish to fry so this approach allowed me to defer work on Addressables, solved an immediate problem, gave me some good learning and fixed some other memory related issues. Eventually though - I will move on to Addressables… just not today.

Wow, well done. Looks like you went through a good deal of work to get this done.

Happy Anniversary Brian (just saw the cake icon)

And thank you.

Another benefit. After I associated the textures with SOs, I pulled texture assets out of their resources folder. During game play (as part of initial load), textures get loaded once with Resources.LoadAll<T>(""). Then caching comes to the rescue so these textures are not constantly loaded/unloaded. Memory usage is a bit higher but much more stable with this approach.

Ultimately though this does further highlight the need to do something more intelligent because caching everything will become a problem once I add more textures/videos/music/large file content.

Happy Anniversary as well Brian.
Ok, so I’m having trouble just calling ResourceRetriever from GetFromId in InventoryItem.cs.

I’ve tried it the way you suggested above but I get the error ResourceRetriever requires one argument. So then I tried
return ResourceRetriever<InventoryItem>.GetFromID(itemID); - I’m getting the error that Inventoryitem cannot be used as a type Parameter T.

I tried
return ResourceRetriever<InventoryItem>().GetFromID(itemID); but this gives an error that i can’t use it like a method.`

So, I’m stymied on how to call this generic class.

For just InventoryItems, you can stick with the built in InventoryItem.GetFromID(). This setup was designed to allow you to retrieve other types of ScriptableObjects.

For ResourceRetriever to work, the Scriptable Object of type T must implement the IHasItemID interface…

Ok. I’m sorry it didn’t work with or without the interface. I’ll just use the standard code. I’m hoping to order a c# reference book by Troelsen since I could use a reference when I’m stuck. That doesn’t mean it will work in unity. For instance, #error version doesn’t work but I’ve since learned that unity has a built-in c# version.

Privacy & Terms