下载AssetBundle的Mono内存问题

下载AssetBundle的Mono内存问题

1)下载AssetBundle的Mono内存问题
​2)Unity 2019运行时获取Hierarchy上预制体资源路径
3)多个Submeshes模型合并后的显示问题
4)ToLua中访问Time.deltaTime为0
5)CacheServer莫名的断开连接


这是第242篇UWA技术知识分享的推送。今天我们继续为大家精选了若干和开发、优化相关的问题,建议阅读时间10分钟,认真读完必有收获。

UWA 问答社区:answer.uwa4d.com
UWA QQ群2:793972859(原群已满员)

Memory

Q:使用协程+UnityWebRequest下载Bundle时分配的内存释放不掉。

下载步骤如下:
1. 使用协程+UnityWebRequest下载Bundle;
2. 使用BinaryWriter将UnityWebRequest.downloadHandler.data的数据写入机器;
3. 调用UnityWebRequest的Dispose函数;
4. 调用Resources.UnloadUnusedAssets(),UnityWebRequest.ClearCookieCache()和System.GC.Collect()。

下载每一个Bundle都会执行如上流程,但是Profiler调试真机发现,分配的内存无法释放,会把Mono内存越撑越大,请问大家遇到过这种情况吗?

A:之前遇到过类似的问题,题主可以参考一下,我们使用的Unity版本是2018.4.31。

不管是之前的WWW还是现在的WebRequest,都是使用的其成员DownloadHandler进行下载。当你访问“.data”属性时,其实访问的是一个“GetData()”函数的包装,这个函数返回的是一段native-memory data buffer的拷贝,这也是问题的根结所在。

第一个可以优化的点就是减少“.data”的使用,用临时变量缓存下来。
第二个就是替换DownloadHandler,Unity提供了多种DownloadHandler,我们当时是下载图片,所以用的是DownloadHandlerTexture,看你的问题,可以试试DownloadHandlerAssetBundle。

参考:https://docs.unity3d.com/ScriptReference/Networking.DownloadHandlerAssetBundle-ctor.html

感谢Joke@UWA问答社区提供了回答,欢迎大家转至社区交流:
https://answer.uwa4d.com/question/5d443ae927d7e5590f6cd84b


Editor

Q:美术希望在编辑器运行的状态下获取场景GameObject实例对应预制体的路径,以前Unity 2017是可以通过var pRoot = PrefabUtility.GetPrefabParent(go); return AssetDataBase.GetAssetPath(pRoot),获取运行时预制路径的。

最近升级到2019发现接口已经更新,PrefabUtility.GetPrefabInstanceHandle(targetGameObject)、PrefabUtility.GetPrefabAssetPathOfNearestInstanceRoot(prefab)等接口都不能在Unity运行的时候去获取Hierarchy里面的GameObject路径。



我问题里面的关键是运行状态,也就是点了播放,然后获取Hierarchy上预制的存储路径。PrefabUtility.GetPrefabAssetPathOfNearestInstanceRoot(prefab)不点播放是可以获取,播放了只能获取Project上预制的存储路径。

A:PrefabUtility.GetNearestPrefabInstanceRoot:获取最近的预制体实例Root。
PrefabUtility.GetPrefabAssetPathOfNearestInstanceRoot:获取预制体路径。

if (PrefabUtility.IsPartOfPrefabInstance(seletedGo))
{
    string prefabAssetPath = PrefabUtility.GetPrefabAssetPathOfNearestInstanceRoot(seletedGo);
}

GetPrefabAssetPathOfNearestInstanceRoot可以获取路径,“PrefabUtility.GetPrefabAssetPathOfNearestInstanceRoot(prefab)” 这个接口传的不是Prefab部分,而是实例的。

如果不行,在Editor时,在它身上挂脚本或者别的方式建立映射,Runtime下再拿。

感谢静风霁@UWA问答社区提供了回答,欢迎大家转至社区交流:
https://answer.uwa4d.com/question/600fe5ea10a17c6c2b09dce1


Mesh

Q:请教下,我测试一个Skinmesh合并功能,发现当Mesh包含多个Submeshes时,合并成功后,无法渲染显示出来。

当测试的Mesh不包含Submeshes时,可以合并显示。难道CombineMeshes只能合并不带Submeshes的Mesh?不知道问题出在哪?有什么解决思路吗?

注:不管是使用“r.sharedMesh.CombineMeshes(combineInstances.ToArray(), false, false); ”带上所有材质,还是“r.sharedMesh.CombineMeshes(combineInstances.ToArray(), true, false) ;”合并一张贴图材质,带多个Submeshes的模型只能合并无法渲染显示出来。不带多个Submeshes的模型能够正常合并显示。

A:测试发现,需要对每个CombineInstance重新指定三角面,才能正常显示带多个Submeshes的模型。

如这段代码:

 foreach (SkinnedMeshRenderer smr in allSkineMeshList)
    {
        for (int sub = 0; sub < smr.sharedMesh.subMeshCount; sub++)
        {
            CombineInstance ci = new CombineInstance();
            ci.mesh = smr.sharedMesh;
            ci.mesh.triangles = smr.sharedMesh.triangles; //这里重新指定

            ci.subMeshIndex = sub;
            ci.transform = matrix * smr.transform.localToWorldMatrix;
            combineInstances.Add(ci);
        }

    }

感谢题主牛头人不服@UWA问答社区提供了回答,欢迎大家转至社区交流:
https://answer.uwa4d.com/question/5fe55b1a10a17c6c2b09d778


Lua

Q:在ToLua中访问Unity的Time.deltaTime始终为nil,赋值给Lua变量也是0。
PS:在ToLua访问Unity API之前已经进行过静态绑定,其他API都可以被Lua正常访问。

为什么ToLua中访问Time.deltaTime为0?


A:Lua的绑定必须写在Lua虚拟机启动之后:

感谢题主yxy@UWA问答社区提供了回答,欢迎大家转至社区交流:
https://answer.uwa4d.com/question/604ad2b3cfa35d5b53669a6a

Editor

Q:客户端打开Cache Server面板测试Connection会发现连接不上,然后点击一下服务器的控制台,Enter一下会提示:

然后客户端才能重新连接,怎么感觉像是失去焦点的意思,这是什么原因呢?

A:Windows在服务器的控制台右击设置属性/默认值 “取消勾选快速编辑模式”。

感谢aladdin@UWA问答社区提供了回答,欢迎大家转至社区交流:
https://answer.uwa4d.com/question/6049be0bcfa35d5b53669a23

封面图来源:VaSplineSnag
VaSplineSnag是提供给UE4关卡设计师的样条曲线工具。
https://lab.uwa4d.com/lab/5b8627da02004fb65977efaf


今天的分享就到这里。当然,生有涯而知无涯。在漫漫的开发周期中,您看到的这些问题也许都只是冰山一角,我们早已在UWA问答网站上准备了更多的技术话题等你一起来探索和分享。欢迎热爱进步的你加入,也许你的方法恰能解别人的燃眉之急;而他山之“石”,也能攻你之“玉”。

官网:www.uwa4d.com
官方技术博客:blog.uwa4d.com
官方问答社区:answer.uwa4d.com
UWA学堂:edu.uwa4d.com
官方技术QQ群:793972859(原群已满员)