笔者介绍:姜雪伟,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内存优化案例讲解的更多相关文章

  1. 【腾讯Bugly干货分享】Android内存优化总结&实践

    本文来自于腾讯Bugly公众号(weixinBugly),未经作者同意,请勿转载,原文地址:https://mp.weixin.qq.com/s/2MsEAR9pQfMr1Sfs7cPdWQ 导语 智 ...

  2. Unity内存优化技术测试案例

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

  3. Unity3D 游戏开发之内存优化

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

  4. Kafka集群优化篇-调整broker的堆内存(heap)案例实操

    Kafka集群优化篇-调整broker的堆内存(heap)案例实操 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.查看kafka集群的broker的堆内存使用情况 1>. ...

  5. [原]unity3d ios平台内存优化(一)

    关于内存优化,人云亦云 各有己见.本文将通过设置Strpping Level ,减少内存使用. 先看三幅图: 1.没做任何优化,默认选项 2.设置Stripping level 为 Use micro ...

  6. 传智播客C语言视频第二季(第一季基础上增加诸多C语言案例讲解,有效下载期为10.5-10.10关闭)

    卷 backup 的文件夹 PATH 列表卷序列号为 00000025 D4A8:14B0J:.│  1.txt│  c语言经典案例效果图示.doc│  ├─1传智播客_尹成_C语言从菜鸟到高手_第一 ...

  7. 深入浅出聊Unity3D项目优化:从Draw Calls到GC

    前言: 刚开始写这篇文章的时候选了一个很土的题目...<Unity3D优化全解析>.因为这是一篇临时起意才写的文章,而且陈述的都是既有的事实,因而给自己“文(dou)学(bi)”加工留下的 ...

  8. Unity3D项目优化(转)

    前言: 刚开始写这篇文章的时候选了一个很土的题目...<Unity3D优化全解析>.因为这是一篇临时起意才写的文章,而且陈述的都是既有的事实,因而给自己“文(dou)学(bi)”加工留下的 ...

  9. 有关memcached企业面试案例讲解

    有关memcached企业面试案例讲解 1.Memcached是什么,有什么作用?    a. memcached是一个开源的.高性能的内存的缓存软件,从名称上看Mem就是内存的意思,而Cache就是 ...

随机推荐

  1. 20145303 实验二 Java面向对象程序设计

    实验二 Java面向对象程序设计 实验内容 初步掌握单元测试和TDD 理解并掌握面向对象三要素:封装.继承.多态 初步掌握UML建模 熟悉S.O.L.I.D原则 了解设计模式 实验要求 1.没有Lin ...

  2. JAVA基本常识及环境搭建

    JAVA基本常识及环境搭建 常用dos命令行 dir 列出当前目录下的文件以及文件夹 md 创建目录 cd 进入指定目录 cd.. 退回到上一级目录 cd/ 退回到根目录 del 删除文件 删除单个文 ...

  3. oracle update set select from 关联更新

    工作中有个需求,现在新表中有一些数据跟老表的基本一样,这样只需要把老表中数据搬到新表中就可以了,同时把不同的字段修改下数据即可,在修改字段时发现,需要指定一个条件,比如主键id,来修改某条记录,这样一 ...

  4. sbt安装与配置

    下载地址:http://www.scala-sbt.org/download.html 当前版本:sbt-0.13.13.tgz 安装 1.解压并赋予权限 [root@hidden util]# ta ...

  5. 爬虫之Fiddler抓取HTTPS设置

    Fiddler抓取HTTPS设置 启动Fiddler,打开菜单栏中的 Tools > Telerik Fiddler Options,打开“Fiddler Options”对话框. 对Fiddl ...

  6. dp_train_f

    Vasya And The Mushrooms 题目大意:有2n个格子,分成上下两行,每行n个,每个格子有蘑菇每秒的生长值(rate),小姑娘从左上角出发(time=0),每秒必须移动,而且只能移动到 ...

  7. 第十篇:Spark SQL 源码分析之 In-Memory Columnar Storage源码分析之 query

    /** Spark SQL源码分析系列文章*/ 前面讲到了Spark SQL In-Memory Columnar Storage的存储结构是基于列存储的. 那么基于以上存储结构,我们查询cache在 ...

  8. from: can't read /var/mail/xxx 解决方法

    在执行一个发包脚本的时候,遇到了如下问题: from: can't read /var/mail/scapy.all 原因:脚本是没有问题的,但它并不是可以被python执行的可执行文件. 解决方法: ...

  9. 公众号菜单中的click

    $params = [ 'button' => [ [ 'type'=>'click', 'name'=>'就送帽子', 'key'=>'V1001_PRESENT', ], ...

  10. MySQL索引底层实现

    一.定义 索引定义:索引(Index)是帮助MySQL高效获取数据的数据结构.本质:索引是数据结构. 二.B-Tree m阶B-Tree满足以下条件: 每个节点至多可以拥有m棵子树. 根节点,只有至少 ...