Unity3D内存优化案例讲解

原创 2017年07月24日 16:00:21

笔者介绍:姜雪伟,IT公司技术合伙人,IT高级讲师,CSDN社区专家,特邀编辑,畅销书作者,已出版书籍:《手把手教你架构3D游戏引擎》电子工业出版社和《Unity3D实战核心技术详解》电子工业出版社等。

CSDN视频网址:http://edu.csdn.net/lecturer/144

游戏开发中涉及到内存优化方面的问题:一是美术方面的问题,二是程序代码的问题。主要是给读者说说程序的问题,以下面代码为例进行讲解。下面这段代码相信读者在程序中经常会这样写,代码存在很多问题,下面就给读者一一道来。

while (currentPreviewNumber < 12) {
            Debug.Log (currentPreviewNumber);
            byte[] tBytes = System.IO.File.ReadAllBytes (Application.persistentDataPath + "/" + currentPreviewNumber + ".jpg");
            Texture2D texture = new Texture2D (100, 100);
            texture.LoadImage (tBytes);

            sprites [currentPreviewNumber] = Sprite.Create (texture, new Rect (0, 0, mCamera.width, mCamera.height),
                new Vector2 (0.5f, 0.5f),
                40);

            currentPreviewNumber++;
        }

有人可能会说,直接使用GC.Collection(),其实情况并不是你想的那样,我们完全可以对代码进行优化,以减少内存分配。主要从以下几点去优化:

1、这些内存分配大部分是Sprite.Create。 它分配内存不好, 解决方案是改变这样的设计, 使用RawImage数组而不是Sprite数组,这种不必要的内存分配将会消失。

2、Texture2D texture = new Texture2D(100,100); 也会分配内存, 由于它始终是100乘100,您可以重新申请它, 使其成为全局,并调用新的Texture2D(100,100); 仅调用一次,在Start函数中, 这极大的节省了内存分配。

3、利用StringBuilder把Application.persistentDataPath + "/" + currentPreviewNumber + ".jpg"串联起来。

4、Application.persistentDataPath 分配内存 将其存储在Start()函数中的临时值中,而不是在while循环中重复调用它。


解决方案一:

public RawImage defaultRawImage;
RawImage[] rawImages;
Texture2D texture = null;
int currentPreviewNumber = 0;
string appPath;
System.Text.StringBuilder imagePath;

void Start()
{
    appPath = Application.persistentDataPath;

    //Init Texture 2D
    texture = new Texture2D(100, 100, TextureFormat.RGB24, false);

    //Init All 12 Raw Images
    rawImages = new RawImage[12];
    for (int i = 0; i < rawImages.Length; i++)
    {
        rawImages[i] = Instantiate(defaultRawImage) as RawImage;
    }

    //Init String Builder
    imagePath = new System.Text.StringBuilder(300);
}

void loadPreviewOptimized()
{
    while (currentPreviewNumber < 12)
    {
        //Debug.Log(currentPreviewNumber);
        imagePath.Capacity = 0;
        imagePath.Append(appPath).Append("/").Append(currentPreviewNumber).Append(".jpg");

        //Read File
        byte[] tBytes = System.IO.File.ReadAllBytes(imagePath.ToString());
        texture.LoadImage(tBytes);

        rawImages[currentPreviewNumber].texture = texture;
        currentPreviewNumber++;
    }
}

byte [] tBytes = System.IO.File.ReadAllBytes(imagePath.ToString()); 代码分配内存来返回字节。 为了摆脱它,使tBytes成为一个全局变量,然后分配内存一次。 当您想通过File.ReadAllBytes停止内存分配时,下面是完整的代码。

解决方案二:

public RawImage defaultRawImage;
RawImage[] rawImages;
Texture2D texture = null;
int currentPreviewNumber = 0;
string appPath;
System.Text.StringBuilder imagePath;
byte[] tBytes;

void Start()
{
    appPath = Application.persistentDataPath;

    //Init Texture 2D
    texture = new Texture2D(100, 100, TextureFormat.RGB24, false);

    //Init All 12 Raw Images
    rawImages = new RawImage[12];
    for (int i = 0; i < rawImages.Length; i++)
    {
        rawImages[i] = Instantiate(defaultRawImage) as RawImage;
    }

    //Init String Builder
    imagePath = new System.Text.StringBuilder(300);
    tBytes = new byte[90000];
}


void loadPreviewOptimized()
{
    while (currentPreviewNumber < 12)
    {
        //Debug.Log(currentPreviewNumber);

        //Reset Capacity before Reading
        imagePath.Capacity = 0;
        imagePath.Append(appPath).Append("/").Append(currentPreviewNumber).Append(".jpg");

        //Read File
        using (System.IO.FileStream myfile = System.IO.File.Open(imagePath.ToString(), System.IO.FileMode.Open, System.IO.FileAccess.Read, System.IO.FileShare.ReadWrite))
        {
            //Check if array size is enough before writing
            if (tBytes.Length >= myfile.Length)
            {
                //OK (Write file to tBytes array)
                myfile.Read(tBytes, 0, (int)myfile.Length);
                texture.LoadImage(tBytes);
            }
            else
            {
                //NOT OK (Resize array size)
                tBytes = new byte[myfile.Length];

                //Write file to tBytes array
                myfile.Read(tBytes, 0, (int)myfile.Length);
                texture.LoadImage(tBytes);
            }

            rawImages[currentPreviewNumber].texture = texture;
            currentPreviewNumber++;
        }
    }
}
现在分配的内存是10.0kb,这很好。 如果要更好地优化,而不是在while循环中使用StringBuilder生成字符串,而是在Start函数中执行一次,

并将这些字符串路径存储到可以在while循环中稍后使用索引的字符串数组。

以上主要是给读者介绍了关于如何优化代码,希望有所帮助。。。。。






版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

Unity3d 3.1内存破解补丁

  • 2010年12月11日 10:40
  • 43KB
  • 下载

unity3d内存池管理工具

  • 2017年08月22日 17:34
  • 48B
  • 下载

Unity3D移动平台内存优化

 最近网友通过网站搜索Unity3D在手机及其他平台下占用内存太大. 这里写下关于Unity3D对于内存的管理与优化. Unity3D 里有两种动态加载机制:一个是Resources.Lo...

Unity3D 内存优化(一)对象池

关于U3D内存优化,一直是游戏开发者头疼的事情,由于在项目中我们会频繁地创建和销毁一些对象,例如:怪物模型或者是UI预设体,但是,部分对象在游戏中是会频繁出现的,例如战斗中的小怪物,假如每次都在使用的...

【Unity3D游戏开发】性能优化之Texture图片空间和内存占用分析(三七)

Unity3D–Texture图片空间和内存占用分析 发表于2014年5月21日由陆泽西 Texture图片空间和内存占用分析。由于U3D并没有很好的诠释对于图片的处理方式,所以很多人一直...

Unity3D 游戏开发之内存优化

项目的性能优化主要围绕CPU、GPU和内存三大方面进行。 无论是游戏还是VR应用,内存管理都是其研发阶段的重中之重。 然而,在我们测评过的大量项目中,90%以上的项目都存在不同程度的内存使...

Unity3D 优化 1 ( cs 实例化与内存变化)

1. 通过 public Object prefab 来实例化 测试 using UnityEngine; using System.Collections; using CodeStage.Adva...

Unity3d内存管理与优化

Unity里有两种动态加载机制:一是Resources.Load,一是通过AssetBundle,其实两者本质上我理解没有什么区别。Resources.Load就是从一个缺省打进程序包里的AssetB...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Unity3D内存优化案例讲解
举报原因:
原因补充:

(最多只允许输入30个字)