【发布时间】:2017-08-30 06:35:49
【问题描述】:
我正在用 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());
之后,我将所有现有控件的源设置为 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()]));
}
当我加载一个房间时,它的控件并且只有它们被加载:
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()]));
}
当我加载新房间时,我会取消旧房间的所有对象。我也对声音、视频甚至网格使用相同的方法 - 它们的源仅在它们处于活动状态时加载,并在它们不再使用时更改为 null。
我这样做是为了避免将所有图像和声音存储在 RAM 中。
问题是,尽管如此,对于这种复杂程度的游戏来说,游戏仍然会消耗大量内存。
标准内存使用量约为 700M - 我觉得太多了。
我怀疑,用于控件而不是字符串的字典和列表会占用所有内存。
例如,我猜这个会复制每个网格:
Dictionary<string, Grid> ResGrids = new Dictionary<string, Grid>();
我的问题:
1) 有没有办法使用我现在使用的方法:存储所有控件源,使它们无效,只加载那些需要的,但改进它? 2)有没有办法将这样的信息存储在文件中,为每个字典或列表创建文件,然后从中加载正在使用的控件的数据。 3) 有没有更好的方法来减少内存使用,而无需进行太大的更改?
提前谢谢你, 叶甫盖尼
【问题讨论】:
-
环顾四周,我认为问题在于您need to freeze the
BitmapImages,否则您似乎每次都加载位图的新副本。或者,只创建一次BitmapImages。 -
"我怀疑什么,[...]" 这可能是你的第一个问题——你不应该怀疑,在尝试改进之前你应该知道。 Visual Studio 以诊断工具的形式为您提供了很好的工具来实际测量应用程序的性能,包括内存使用情况。拍摄内存快照很可能会为您提供足够有用的信息来确定您的问题(如果有的话)。