2017-08-30 94 views
0

我在C#上制作游戏。问题是,它使用大量的RAM,用于这种类型和质量的游戏。我制作的游戏消耗太多内存

我会尽量给出一个简短但足够好的描述。当然,我不会给出完整的代码,但试图展示我认为相关的东西。

游戏中有一些网格,每个网格代表一个游戏室,每个网格内有图像和按钮。图像始终是静态图片。但是有很多图像和按钮。

在我的第一种方法中,我决定将每个图像和声源存储在列表或字典中,这些列表和词典是在游戏开始时创建的,只创建一次。

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>(); 

字典存储图像或按钮或网格名称,它是从xaml的原始源文件。它们也在开始时加载并且仅加载一次。

 image_path.Add("imgBloodyPodBlood", imgBloodyPodBlood.Source.ToString()); 
     image_path.Add("imgBloodyPodShardsBlood", imgBloodyPodShardsBlood.Source.ToString()); 
     image_path.Add("imgComputerConversation", imgComputerConversation.Source.ToString()); 

在那之后,我对所有现有控件设置源为空:

 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()]));    
    } 

当我打开一个房间,它的控制,只有他们被加载:

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()]));    
    } 

当我加载新房间,取消旧房间的所有对象。我还对声音,视频甚至是网格使用了相同的方法 - 它们的源只在它们处于活动状态时加载,并且在它们不再使用时更改为空。

我这样做是为了避免将所有图像和声音存储在RAM中。

问题是,尽管如此,对于这种复杂程度的游戏,游戏仍然消耗大量的内存。

标准的内存使用量大约是700M - 我觉得它太多了。

我怀疑,控件的字典和列表,而不是字符串,消耗所有的内存。

例如,我想这一个使每个网格的副本:

Dictionary<string, Grid> ResGrids = new Dictionary<string, Grid>();

我的问题:

1)是否有使用我现在使用的方法的方式:存储所有控制来源,取消它们,只加载那些需要的,但改进它? 2)有没有办法在文件中存储这样的信息,为每个字典或列表创建文件,然后从中加载正在使用的控件的数据。 3)有没有更好的方法来减少内存使用量,而不会做出太大的改变?

谢谢你在前进, 叶甫盖尼

+0

环顾四周,我认为问题是你[需要冻结'BitmapImage's](https: //stackoverflow.com/a/802394/1270789),否则你每次都加载一个位图的新副本,看起来好像。或者,只能创建一次'BitmapImage'。 –

+0

“我怀疑,”这可能是你的第一个问题 - 你不应该怀疑,在尝试改进某些东西之前你应该知道。 Visual Studio为您提供了很好的工具,以诊断工具的形式实际衡量您的应用性能,包括内存使用情况。如果存在快照,拍摄快照很可能会为您提供足够有用的信息来识别您的问题。 – Milster

回答

0

运行性能测试(Alt + F2在VS),然后你就会知道应用程序被消耗RAM。

此外,您没有发布太多的代码,所以它将很难直接帮助你,但保持这么多Dictionaries可能不是一个好主意。进入OOP并为每个房间创建包含所需数据的特定对象。这只是初始化,我们不知道你以后在做什么代码,所以它很难帮助