The biggest problem I ran into has to do with asset lifetime management. That is, allowing for ad-hoc creation or loading and unloading of (list to follow):
Textures
Models
Storyboards
Skeletons
Scripts
Audio Samples
Fonts
Skyboxes
Shaders/Shader programs
... and anything else which a game developer might want to create/destroy, or load/unload.
To cope with this generics can be quite handy. A master asset manager class can hold these types of things for you so that you don't need to declare instances of each type in a class. The asset manager can also hold copies for you so that you don't need to recreate then when they are needed. Some examples.
// Change the texture of a sprite to a ghost
Sprite.Texture := Assets.Textures[SGhostTexture];
Sprite.Shader := Assets.ShaderPrograms[SEtherealShader];
// Add a scary sound sample to an audio bank and loop it
AudioBank := Audio.Banks.Add(Assets.Sounds[SScaryMusic]);
AudioBank.Looping := True;
AudioBank.Play;
// Load up a slimy looking font
FontWriter.Font := Assets.Fonts[SSlimeFont];
Where Assets is a global TAssetManager containing all possible assets
type
TAssetManager = class(TManaged)
public
property Sprites: TManagedCollection<TSprite> read GetSprites;
property Textures: TManagedCollection<TTexture> read GetTextures;
property Sounds: TManagedCollection<TAudioSamples> read GetSounds;
// and so on
end;
The problem then comes in where you have certain sprites/sounds allocated at different times, for example changing/advancing game levels. One solution is just to load every possible asset before the game starts, but this is kind of wasteful and also possibly not feasible due to hardware resource constraints. Perhaps you have a game selections screen. There is no reason the assets specific to that screen should be taking up audio banks and texture memory after you start the game. Okay then you need a clean way to group all the assets for different stages together such that they can all be loaded and unloaded en mass when preparing to enter or exit a scene. Then things can get a little messy from there.
Now this where managed types can help. If the asset manager can hold a reference count to asset items (via a managed collection class), and a class can also hold the same references directly, as in not inside a container but declared directly, then grouping assets can be simplified a bit. Perhaps a TGameSelectScene can hold direct copies of the assets it needs and use Assets (TAssetManager) to request them, The scene can then hold references to these assets and remove them from the asset manager, but when the scene is released so are its very specific assets.
I really haven't come up with an acceptable solution to this problem yet. I also need better integration with a compression library to store assets before they are uncompressed and loaded from some kind of WAD file (like how Doom used to handle this stuff). For now assets are compressed and linked directly into the exe/application, but I feel they should be in separate compressed files. Perhaps grouped by scene (TGameSelectScene would have it's own WAD).
https://en.wikipedia.org/wiki/Doom_WAD
Anyhow the point is to make managing game of assets as transparent as possible to the game programmer, where he can request textures, shaders, fonts, 3D models, or whatever, without the burden of remembering when to create and destroy these things.