我的游戏的基准内存使用量约为 315 MB。然而,调用以下函数会导致内存使用量急剧上升,稳定在 480 MB 左右,同时达到 580 MB 甚至更多的峰值,并伴有内存警告甚至崩溃。
发生了什么:首先,
TakeScreenshot
IEnum 被连续调用三次,这是最大值。计算一次会话中的屏幕截图数量。其次,调用函数 SendEmailTask
显示所有三张图片供用户选择一张。通过选择图片“#1”,功能SendImage1
被触发。
也许有人可以指出我在哪里以及如何找回一些记忆,那真是太棒了!
所有相关代码都应该在这里:
public class Picture : MonoBehaviour {
private int ssCount = 0;
private Sprite cachedImage1sprite;
private Sprite cachedImage2sprite;
private Sprite cachedImage3sprite;
private Texture2D cachedImage1;
private Texture2D cachedImage2;
private Texture2D cachedImage3;
private Texture2D JPGtex1;
private Texture2D JPGtex2;
private Texture2D JPGtex3;
private Texture2D tex;
void Awake () {
}
// Use this for initialization
void Start () {
JPGtex1 = new Texture2D (2, 2, TextureFormat.RGB24, false );
JPGtex2 = new Texture2D (2, 2, TextureFormat.RGB24, false );
JPGtex3 = new Texture2D (2, 2, TextureFormat.RGB24, false );
// Create a texture the size of the screen, RGB24 format
int width = Screen.width;
int height = Screen.height;
tex = new Texture2D( width, height, TextureFormat.RGB24, false );
}
// Update is called once per frame
void Update () {
if (ssCount == 0) {
SendEmail.interactable = false;
TakePhoto.interactable = true;
} else if (ssCount == 1) {
SendEmail.interactable = true;
} else if (ssCount == 3) {
TakePhoto.interactable = false;
}
//Debug.Log (ssCount);
}
void SendEmailTask(){
if (ssCount == 3) {
cachedImage1 = SA.IOSNative.Storage.AppCache.GetTexture ("IMAGE_1");
cachedImage2 = SA.IOSNative.Storage.AppCache.GetTexture ("IMAGE_2");
cachedImage3 = SA.IOSNative.Storage.AppCache.GetTexture ("IMAGE_3");
ImagePicker.SetActive (true);
//Image1
Rect rec1 = new Rect(0, 0, cachedImage1.width, cachedImage1.height);
cachedImage1sprite = Sprite.Create(cachedImage1, rec1, new Vector2(0,0),1);
Image1.image.sprite = cachedImage1sprite;
//Image2
Rect rec2 = new Rect(0, 0, cachedImage2.width, cachedImage2.height);
cachedImage2sprite = Sprite.Create(cachedImage2, rec2, new Vector2(0,0),1);
Image2.image.sprite = cachedImage2sprite;
//Image3
Rect rec3 = new Rect(0, 0, cachedImage3.width, cachedImage3.height);
cachedImage3sprite = Sprite.Create(cachedImage3, rec3, new Vector2(0,0),1);
Image3.image.sprite = cachedImage3sprite;
SA.IOSNative.Storage.AppCache.Remove ("IMAGE_1");
SA.IOSNative.Storage.AppCache.Remove ("IMAGE_2");
SA.IOSNative.Storage.AppCache.Remove ("IMAGE_3");
}
}
IEnumerator TakeScreenshot() {
// Wait till the last possible moment before screen rendering to hide the UI
yield return null;
GameObject.Find("Buttons").GetComponent<Canvas>().enabled = false;
FlashImage();
// Wait for screen rendering to complete
yield return new WaitForEndOfFrame();
// Create a texture the size of the screen, RGB24 format
int width = Screen.width;
int height = Screen.height;
// Read screen contents into the texture
tex.ReadPixels( new Rect(0, 0, width, height), 0, 0 );
tex.Apply();
//byte[] screenshot = tex.EncodeToPNG();
print("Size is " + tex.width + " by " + tex.height);
if (ssCount == 0) {
SA.IOSNative.Storage.AppCache.Save ("IMAGE_1", tex);
ssCount++;
} else if (ssCount == 1) {
SA.IOSNative.Storage.AppCache.Save ("IMAGE_2", tex);
ssCount++;
} else if (ssCount == 2) {
SA.IOSNative.Storage.AppCache.Save ("IMAGE_3", tex);
ssCount++;
}
IOSCamera.Instance.SaveTextureToCameraRoll(tex); //Save to Cameraroll
// Show UI after we're done
GameObject.Find("Buttons").GetComponent<Canvas>().enabled = true;
}
public void SendImage1() {
byte[] screenshot1;
screenshot1 = cachedImage1.EncodeToJPG ();
if (Facebook == false) {
JPGtex1.LoadImage (screenshot1);
TextureScale.Bilinear (JPGtex1, 1200, 900);
IOSSocialManager.Instance.SendMail (SubjectText, EmailText, "", JPGtex1);
} else {
StartCoroutine(UploadToPage(screenshot1));
}
backToGame ();
}
public void backToGame() {
Destroy (cachedImage1sprite);
Destroy (cachedImage2sprite);
Destroy (cachedImage3sprite);
SA.IOSNative.Storage.AppCache.Remove ("IMAGE_1");
SA.IOSNative.Storage.AppCache.Remove ("IMAGE_2");
SA.IOSNative.Storage.AppCache.Remove ("IMAGE_3");
Destroy(cachedImage1);
Destroy(cachedImage2);
Destroy(cachedImage3);
cachedImage1 = null;
cachedImage2 = null;
cachedImage3 = null;
Image3Obj.SetActive (true);
ImagePicker.SetActive (false);
}
}
编辑
两次执行例程后的详细内存分析器:
两次执行例程后的 Xcode 内存分析器:
来自您的分析报告;
您在网格和纹理 2D 资源上使用了大量内存 - 这对我来说意味着您可能正在绘制它们/向用户隐藏它们,而不是实际从内存中删除它们。考虑到您还加载了另外 120+ MB 的网格,Texture2D 资源中的 50+ MB 有点奇怪。我假设这是一个 3D 游戏,但有 2D UI?如果是这样,那么 50MB 花在 Texture2D 资源上就相当多了。
“对象”就是你所认为的那样——它们就是对象。实例化类或包含附加组件的游戏对象。因此,如果您创建了一个 Player GameObject,并附加了一个“playerStats”对象,其中包含几个用于健康、速度、耐力等的变量,那么这将算作 2 个对象。
80MB 对于对象来说并不算太令人担心。在我看来,对于一款针对 iOS 的游戏来说,您使用的 Texture2D 和 Meshes 相当高。确保您使用适合移动设备的模型以及分辨率不太高的纹理。
我在 iOS 中的音频文件也遇到了类似的问题,我不知道这是否是你的情况。
我在内存上加载了 20mb+ 的大音频文件来处理它们,然后释放内存,问题是 xcode 分析器中的内存不断增加。这是由内存碎片引起的,您可以在这里阅读更多相关信息:https://stackoverflow.com/a/3770593/4024219
我的解决方案是以小块的形式加载文件并重用我的数组,而不是创建和销毁新的数组。