手机游戏第一次启动基本上都会做资源释放的操作,这个时候需要考虑存储空间是否足够,但是Unity没有自带获取设备存储空间大小的

接口,需要调用本地方法分别去android或ios获取,这样挺麻烦的。而且资源释放是耗时的,这个时候,如果其他应用在做后台下载,万一
把空间占完了怎么办呢。可能有人会想到释放资源的时候每一次写操作都获取一次存储空间的大小,这样当然能解决问题,但是同时也极大的
延长了资源释放的时间,毕竟每一次本地方法的调用还是比较耗时的。
    既然调用本地方法麻烦又耗时,那有没有什么方法不用调用本地方法呢?
    首先,我尝试了一下直接不做任何判断,只加了一个try catch,看看空间满了能不能捕获到异常。当然第一件事是把手机给塞满。嗯,我的安卓机还有8G的存储空间,那我用程序创建几个1G的空文件吧。
                int buffer =  *  * ;
using (var tempStream = File.Create(tempPath))
{
tempStream.SetLength(buffer);
tempStream.Flush();
tempStream.Close();
}
  文件创建出来了,然后查看文件的大小确实是1GB。然后再去设置里面查看设备的剩余空间,还是8G。嗯?不对。我再创建8个文件,还是不对。
看来占位文件是不计大小的,虽然看起来有那么大。。。那么改一下生成方式,老老实实写文件
                int buffer =  *  * ;
using (var tempStream = File.Create(tempPath))
{
tempStream.Write(new byte[buffer], , buffer);
//tempStream.SetLength(buffer);
tempStream.Flush();
tempStream.Close();
}
  这次对了,虽然慢了点,但也比从外部拷贝文件到手机里快多了。既然方法对了那就多创建几个文件,当创建到第9个文件时,catch到异常,提示的 "Disk full XXX"。看来完全可以通过try catch的方式来判断磁盘空间是否够用嘛。当然catch到的不一定都是Disk full的异常,也有可能是out of memory。但是总归是释放资源失败了,要给玩家一个交代,那么统一提示为 “释放资源失败,可能磁盘空间满了“,然后这个时候自动上报异常,去后台查看就好了(我是用的Bugly)。如果你给玩家提示一个什么 “释放资源失败,内存溢出了“,玩家反而是一脸懵逼。
    所以,完全可以用try catch来替换通过本地方法获取磁盘存储空间的方式。
    我把获取本地方法的地方给去掉,加了一个try catch,然后运行游戏,释放资源
                        xxxxxxxx
....
try
{
fileName = Path.Combine(unRootPath, fileName);
fileName = fileName.Replace('\\', '/');
using (FileStream streamWriter = File.Create(fileName))
{
WriteFile(s, streamWriter); streamWriter.Flush();
streamWriter.Close();
}
++nWriteCount;
}
catch (Exception ex)
{
UpdateLog.ERROR_LOG(ex.Message);
return;
}
....
xxxxxxx
        protected int _bufferSize = ;
protected byte[] _buffer = new byte[]; private void WriteFile(ZipInputStream zi, FileStream outFile)
{
int size = ;
while((size = zi.Read(_buffer, , _bufferSize)) > )
{
outFile.Write(_buffer, , size);
}
}
    等待资源释放触发catch,但是,恐怖的事情发生了。游戏闪退了,闪退了,闪退了。。。
我查了下log,catch信息是打印出来了,也是 Disk full,为啥游戏就闪退了?刚刚还写了测试代码用来创建大文件,都没有闪退呀。反复比较了一下代码,发现是bufferSize不一样,一个1k,一个1G。是这个引起的?我把bufferSize改成2k,不行。4k, 不行,6k,还是不行。1MB,可以了~~~隐约记得socket底层的buffer貌似是8kb,难道写文件操作内部也有个8kb的buffer。我把size改成10k,也没闪退。看来还真有可能。
    反编译System.IO.FileStream这个dll,还真有一个默认8kb的设置
 
 
    看到这个代码,buffer大于8k和小于8k,底层写文件走的逻辑是不同的,在if里面会抛出写文件失败的异常,else里面可能就会卡死。当然这也是推测,哪位大神知道原因的,麻烦告知一下。
    好了,把buffer设置为10k,一样没有闪退,完美触发异常,弹出友好提示。
        protected int _bufferSize = 1024 * 10;
        protected byte[] _buffer = new byte[1024 * 10];
 
    总结:通过try catch来捕获磁盘空间不足是可行的,但是需要写文件的bufferSize大于8k, 太大没必要,10k比较合适。

Unity3d: 资源释放时存储空间不足引发的思考和遇到的问题的更多相关文章

  1. Unity3D 导入贴图、模型等资源文件时自动设置参数

    脚本继承至AssetPostprocessor, 存放在Editor目录下! using UnityEngine; using System.Collections; using UnityEdito ...

  2. Unity3D内存释放

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

  3. KEngine:Unity3D资源的打包、加载、调试监控

    资源模块做什么? 资源模块——ResourceModule,是KEngine中最核心的模块,其他模块基本或多或少的对它有依赖,它主要的功能是:资源打包.路径定义.资源管理.资源调试. 资源模块对Uni ...

  4. 基于webrtc的资源释放问题(一)

    基于webrtc的资源释放问题(一) ——重复释放webrtc的相关资源 背景: 视频通讯大都只是作为一个功能存在于各种应用中,比如微信,qq .既然只是应用的一部分,这样就涉及反复的开启和关闭视频通 ...

  5. C#资源释放

    转自:http://www.cnblogs.com/psunny/archive/2009/07/07/1518812.html 深刻理解C#中资源释放 今天我的一个朋友看到我写的那篇<C#中用 ...

  6. Delphi中关于资源释放(Free,Relealse,FreeAndNil)

    根据日常编程经验,得出一些Delphi中关于资源释放的体会. 假如有对象Obj为TObject类型: 1) Obj.Free直接释放资源后,调用OnDestroy事件,但是没有将Obj指针值置为Nil ...

  7. 深刻理解C#中资源释放

    今天我的一个朋友看到我写的那篇<C#中用AJAX验证用户登录>时,给我指出了点小毛病.就是在用户登录时,如果用户登录失败,在下面这段代码中,都会new出来一个User对象,如果连续登录失败 ...

  8. .net 资源释放(托管资源和非托管资源)

    1.托管资源 像int.float.DateTime等都是托管资源:net中80%的资源都是托管资源: 托管资源的回收通过GC(垃圾回收器)自动释放分配给该对象的内存,但无法预测进行垃圾回收的时间,我 ...

  9. unity3d 资源文件从MAX或者MAYA中导出的注意事项

    unity3d 资源文件从MAX或者MAYA中导出的注意事项     1.首先,Unity3d 中,导出带动画的资源有2种导出方式可以选择:    1) 导出资源时,只导出一个文件,保留模型,骨骼和所 ...

随机推荐

  1. JSON 解析工具的封装(Java)

    JSON 解析工具的封装(Java) 一直想有一个属于自己的JSON工具,今天终于弄好了..... 1.添加pom依赖包 <!--json解析--> <dependency> ...

  2. 【WPF】学习笔记(一)——做一个简单的电子签名板

    参加实习(WPF)已经有两个多周的时间了,踩了一些坑,也算积累了一些小东西,准备慢慢拿出来分享一下.(●'◡'●) 这次呢就讲讲一个简单的电子签名板的实现. 先上张图(PS:字写得比较丑,不要太在意哈 ...

  3. 一天精通MongoDB数据库

    什么是MongoDB ? MongoDB 是由C++语言编写的,是一个基于分布式文件存储的开源数据库系统. 在高负载的情况下,添加更多的节点,可以保证服务器性能. MongoDB 旨在为WEB应用提供 ...

  4. 自动化运维:使用psutil和paramiko读取远程主机信息

    1.前言  今天大致看了下自动化运维的东西,里面介绍到了psutil模块,其封装了linux 下的大部分shell命令,用起来比较方便.但是基本都是介绍在本地如何使用,而实际情况大家很少这样使用,一般 ...

  5. 你跟上技术趋势了么? 来看看这10场2017热门it技术会议!

    2016年各类大会让人应接不暇,技术圈儿最不缺的就是各种大会小会,有的纯干货,有的纯广告.作为一名技术开发者,参加了几场大会,你是不是也开始思忖:究竟哪些会议才值得参加?下面活动家为你推荐几场2017 ...

  6. 利用LinkedList生成一副扑克牌

    import java.util.LinkedList; import java.util.Random; //自定义一个Poker类,用于存储扑克的信息(花色.数字) class Poker{ St ...

  7. 关于“foreach循环”中遇到的几个问题总结

    1.列表页面用"foreach循环"的时候数据没有显示,此时需要检查你对象模型中属性的首字母是否大写,切记不能大写(本人在做一个项目的时候,对象模型是别人建立的,属性首字母大写了, ...

  8. 转载+++++iptables详解+++++转载

    转载:http://blog.chinaunix.net/uid-26495963-id-3279216.html 一.前言 防火墙,其实说白了讲,就是用于实现Linux下访问控制的功能的,它分为硬件 ...

  9. 使用 Mono.Cecil 辅助 Unity3D 手游进行性能测试

    Unity3D 引擎在  UnityEngine 名字空间下,提供了  Profiler 类(Unity 5.6 开始似乎改变了这个名字空间),用于辅助对项目性能进行测试.以 Android 平台为例 ...

  10. MyEclipse修改项目名称后,部署到tomcat问题。

    1.问题描述: 修改项目名称后,部署到tomcat server,部署出来的文件夹名还是旧的名称. 2.解决方案: 光把项目重命名是不够的,还要修改一下Myeclipse里面的配置. a). 工程名- ...