I am making a game on C#. The problem is, that it uses large amounts of RAM, for the games of such type and quality.
I'll try to give a short, but good enough description. I, of course, won't give full code, but try to show what I think is relevant.
The game has some grids, where each grid represents a game room, inside each grid, there are images and buttons. The images are always static pictures. But there are many images and buttons.
In my first approach, I decided to store each image and sound source in a list or dictionary, those lists and dictionaries are created when game starts, created only once.
Dictionary<string, string> voice_path = new Dictionary<string, string>();
Dictionary<string, string> video_path = new Dictionary<string, string>();
Dictionary<string, string> inventory_path = new Dictionary<string, string>();
Dictionary<string, Image> inventory_convert = new Dictionary<string, Image>();
Dictionary<string, string> area_path = new Dictionary<string, string>();
static Dictionary<string, string> CameFrom = new Dictionary<string, string>();
Dictionary<string, Visibility> ConvertVisibility = new Dictionary<string, Visibility>();
Dictionary<string, Control> ResObjects = new Dictionary<string, Control>();
Dictionary<string, Grid> ResGrids = new Dictionary<string, Grid>();
Dictionary<string, System.Windows.Controls.Image> ResImages = new Dictionary<string, System.Windows.Controls.Image>();
Dictionary<string, TextBlock> ResTextBlocks = new Dictionary<string, TextBlock>();
Dictionary<string, Label> ResLabels = new Dictionary<string, Label>();
Dictionary<string, System.Windows.Controls.Image> to_fill_images_dictionary = new Dictionary<string, System.Windows.Controls.Image>();
public static Dictionary<string, Action> Merge = new Dictionary<string, Action>();
List <string> ObjectsVisibility = new List <string>();
public static List <string> StoryElements = new List <string>();
static List <string> OpenObjects = new List<string>();
List<string> to_fill_images_list = new List<string>();
List<MediaElement> Sounds = new List<MediaElement>();
List<MediaElement> Musics = new List<MediaElement>();
List<MediaElement> Voices = new List<MediaElement>();
List<MediaElement> Videos = new List<MediaElement>();
List<Image> Images = new List<Image>();
Dictionary<string, string> image_path = new Dictionary<string, string>();
Dictionaries store image or button, or grid name and it's original source file from xaml. They are also loaded at the beginning and only once.
image_path.Add("imgBloodyPodBlood", imgBloodyPodBlood.Source.ToString());
image_path.Add("imgBloodyPodShardsBlood", imgBloodyPodShardsBlood.Source.ToString());
image_path.Add("imgComputerConversation", imgComputerConversation.Source.ToString());
After that, I set source for all existing controls to null:
imgBloodyPodBlood.Source = null;
imgBloodyPodShardsBlood.Source = null;
imgComputerConversation.Source = null;
void ShowAirlock()
{
areaAirlock.Background = new ImageBrush(new BitmapImage(new Uri(area_path[areaAirlock.Name.ToString()], UriKind.Relative)));
imgAirlock_Dark.Source = new BitmapImage(new Uri(image_path[imgAirlock_Dark.Name.ToString()]));
imgAirlock_Dark_Door.Source = new BitmapImage(new Uri(image_path[imgAirlock_Dark_Door.Name.ToString()]));
imgAirlock_Dark_Suit.Source = new BitmapImage(new Uri(image_path[imgAirlock_Dark_Suit.Name.ToString()]));
imgAirlock_Light_Door.Source = new BitmapImage(new Uri(image_path[imgAirlock_Light_Door.Name.ToString()]));
imgAirlock_Light_Suit.Source = new BitmapImage(new Uri(image_path[imgAirlock_Light_Suit.Name.ToString()]));
imgAirlockLamp.Source = new BitmapImage(new Uri(image_path[imgAirlockLamp.Name.ToString()]));
}
And when I load a room, its controls and only them are loaded:
void ShowAirlock()
{
areaAirlock.Background = new ImageBrush(new BitmapImage(new Uri(area_path[areaAirlock.Name.ToString()], UriKind.Relative)));
imgAirlock_Dark.Source = new BitmapImage(new Uri(image_path[imgAirlock_Dark.Name.ToString()]));
imgAirlock_Dark_Door.Source = new BitmapImage(new Uri(image_path[imgAirlock_Dark_Door.Name.ToString()]));
imgAirlock_Dark_Suit.Source = new BitmapImage(new Uri(image_path[imgAirlock_Dark_Suit.Name.ToString()]));
imgAirlock_Light_Door.Source = new BitmapImage(new Uri(image_path[imgAirlock_Light_Door.Name.ToString()]));
imgAirlock_Light_Suit.Source = new BitmapImage(new Uri(image_path[imgAirlock_Light_Suit.Name.ToString()]));
imgAirlockLamp.Source = new BitmapImage(new Uri(image_path[imgAirlockLamp.Name.ToString()]));
}
When I load the new room, I nullify all objects of old one. I also use same approach with sounds, videos and even grids - their source is only loaded when they are active, and changed to null when they are no longer use.
I am doing it, to avoid storing all images and sounds in RAM.
The problem is, that despite all this, game still consumes very large amount of memory, for the games of this level of complexity.
The standard memory usage is about 700M - and I find it too much.
What I suspect, that dictionaries and lists that are for controls, and not strings, consume all the memory.
For example, I guess this one makes a copy of each grid:
Dictionary<string, Grid> ResGrids = new Dictionary<string, Grid>();
My questions:
1) Is there a way to use approach I am using now: storing all controls sources, nullifying them, the loading only those needed, but improve it? 2) Is there a way to store information like this in a file, to make file for each dictionary or list, then load from them data for controls that are being used. 3) Is there a better way to reduce memory usage, without making too drastic changes?
Thank you in advance, Evgenie