unity www在android端不释放内存问题解决方案
最近在优化unity游戏项目内存占用,游戏打开时会先从包里解压一部分资源到本地,原本是使用的www进行解压,解压的包体有400M,解压完毕后发现unity竟然不会释放这部分内存给系统,而是继续持有,查询了很多相关资料后发现这是C#的问题,C#的设计理念是一但应用可以申请400M的内存进行解压,那这400M内存也不用还给系统,应用后续的其它内存申请可复用之前申请的内存空间,减少数据吞吐提升运行效率,
最近在优化unity游戏项目(android)内存占用,游戏打开时会先从包里的zip文件中解压一部分资源到本地,原本是使用的www进行解压,解压的包体有400M,解压完毕后发现unity竟然不会释放这部分内存给系统,而是继续持有.
查询了很多相关资料后发现这是C#的设计理念,应用如果可以成功申请到400M的内存进行解压,那这400M内存不会还给系统,而是被系统标记为空闲,后续如果要申请其它内存,会复用之前申请的这400M内存空间,减少数据吞吐提升运行效率,可是经实测发现,后续申请的内存并没有复用这400M,而是另外开辟了别的内存空间,这就无法接受了.
在试了很多办法无果后,决定抛弃C#,拥抱原生java吧,随即用java重新写了一个解压逻辑,没想到解压速度比c#还快很多,再辅以线程的帮助,解压时的loading动画也顺畅了很多,一举两得:
下面给出代码,一个是从apk包里解压文件,一个是从obb包里解压文件(如果采用obb分包,读取文件的路径略有不同)
public void unzipFromApk(Context context, String filePath) {
new Thread(new Runnable(){
@Override
public void run(){
String destination = getExternalFilesDir("StreamingAssets").getAbsolutePath();
//String destination2 = getExternalFilesDir("").getAbsolutePath() + "/StreamingAssets/";
Log.d("Unzip", "destination = " + destination);
//Log.d("Unzip", "destination2 = " + destination2);
try {
//FileInputStream inputStream = new FileInputStream(filePath);
ZipInputStream zipStream = new ZipInputStream(context.getAssets().open(filePath));
ZipEntry zEntry = null;
String szName = "";
while ((zEntry = zipStream.getNextEntry()) != null) {
Log.d("Unzip", "Unzipping " + zEntry.getName() + " at "
+ destination);
szName = zEntry.getName();
if (zEntry.isDirectory()) {
szName = szName.substring(0, szName.length() - 1);
String folderName = destination + File.separator + szName;
File folder = new File(folderName);
folder.mkdirs();
zipedFileNum++;
} else {
String fileName = destination + File.separator + szName;
File file = new File(fileName);
if (!file.exists()) {
//Log.e(TAG, "Create the file:" + outPathString + File.separator + szName);
file.getParentFile().mkdirs();
file.createNewFile();
}
FileOutputStream fout = new FileOutputStream(fileName);
BufferedOutputStream bufout = new BufferedOutputStream(fout);
byte[] buffer = new byte[1024];
int read = 0;
while ((read = zipStream.read(buffer)) != -1) {
bufout.write(buffer, 0, read);
}
zipedFileNum++;
zipStream.closeEntry();
bufout.close();
fout.close();
}
}
zipStream.close();
Log.d("Unzip", "Unzipping complete. path : " + destination);
} catch (Exception e) {
Log.d("Unzip", "Unzipping failed");
e.printStackTrace();
}
}
}).start();
}
public void unzipFromObbFile(Context context, String filePath) {
new Thread(new Runnable(){
@Override
public void run(){
String destination = getExternalFilesDir("StreamingAssets").getAbsolutePath();
try {
//获取Obb扩展文件路径
String path = getObbDir().getPath() + "/main." +getVersionCode(MainActivity.this) + "." + getAppPackageName(MainActivity.this) + ".obb";
//得到obb文件实例
ZipResourceFile expansionFile = new ZipResourceFile(path);
//读取
InputStream inputStream = expansionFile.getInputStream("assets/" + filePath);
if (inputStream == null)
{
Log.d("Unzip", "zip file not found in assets");
inputStream = expansionFile.getInputStream(filePath);
}
else
{
Log.d("Unzip", "zip file found in assets!");
}
//FileInputStream inputStream = new FileInputStream(filePath);
ZipInputStream zipStream = new ZipInputStream(inputStream);
ZipEntry zEntry = null;
String szName = "";
while ((zEntry = zipStream.getNextEntry()) != null) {
Log.d("Unzip", "Unzipping " + zEntry.getName() + " at "
+ destination);
szName = zEntry.getName();
if (zEntry.isDirectory()) {
szName = szName.substring(0, szName.length() - 1);
String folderName = destination + File.separator + szName;
File folder = new File(folderName);
folder.mkdirs();
zipedFileNum++;
} else {
String fileName = destination + File.separator + szName;
File file = new File(fileName);
if (!file.exists()) {
//Log.e(TAG, "Create the file:" + outPathString + File.separator + szName);
file.getParentFile().mkdirs();
file.createNewFile();
}
FileOutputStream fout = new FileOutputStream(fileName);
BufferedOutputStream bufout = new BufferedOutputStream(fout);
byte[] buffer = new byte[1024];
int read = 0;
while ((read = zipStream.read(buffer)) != -1) {
bufout.write(buffer, 0, read);
}
zipedFileNum++;
zipStream.closeEntry();
bufout.close();
fout.close();
}
}
zipStream.close();
inputStream.close();
Log.d("Unzip", "Unzipping complete. path : " + destination);
} catch (Exception e) {
Log.d("Unzip", "Unzipping failed");
e.printStackTrace();
}
}
}).start();
}
下面是我在搜寻解决方案时查到的一些相关资料,也是unity申请内存后不释放的类似问题:
https://forum.unity.com/threads/big-byte-array-will-cause-memory-leak.403496/
更多推荐
所有评论(0)