// Use this for initialization IEnumerator Start() { yield return(FullUnloadAndGC()); Time.maximumDeltaTime = 10; Application.targetFrameRate = 1000; //计算每帧Overhead float baseFrameTime = 0; int baseFrameCount = 33; for (int i = 0; i < baseFrameCount; i++) { yield return(UtilityOwn.Yield.WaitForEndOfFrame); baseFrameTime += Time.deltaTime; } baseFrameTime /= baseFrameCount; Debug.LogFormat("average delta time of {0} frames: {1}", baseFrameCount, baseFrameTime); mInitTextureSamples = GetTextureMemorySamples(); if (testAssetPathList.Count == 0) { ReloadAssetPath(ref testAssetPathList); } var now = DateTime.Now; string fileName = string.Format("AssetProfilingReport_{0:d4}{1:d2}{2:d2}_{3:d2}{4:d2}{5:d2}.csv", now.Year, now.Month, now.Day, now.Hour, now.Minute, now.Second); mSavePath = Path.Combine(Path.GetDirectoryName(Application.dataPath), fileName); mProgress = 0; System.Text.StringBuilder builder = new System.Text.StringBuilder(); StreamWriter sw = new StreamWriter(mSavePath, false, System.Text.Encoding.UTF8); ProfilingReport.ExportColomnName(builder, topFrameCount); sw.Write(builder.ToString()); builder.Length = 0; for (mProgress = 0; mProgress < testAssetPathList.Count; mProgress++) { builder.Length = 0; yield return(AnalyzeSingleAsset(testAssetPathList[mProgress], baseFrameTime)); mTempReport.Export(builder); sw.Write(builder.ToString()); sw.Flush(); } sw.Close(); }
IEnumerator AnalyzeSingleAsset(string assetPath, float baseFrameTime) { mTempReport = new ProfilingReport(); mTempReport.path = assetPath; //清除缓存资源 yield return(FullUnloadAndGC()); //独立的代码块来声明局部变量,限定作用域 { //加载 float t1 = Time.realtimeSinceStartup; GameObject targetObject = AssetDatabase.LoadAssetAtPath <GameObject>(assetPath); float t2 = Time.realtimeSinceStartup; mTempReport.loadTime = (t2 - t1) * 1000; yield return(UtilityOwn.Yield.WaitForEndOfFrame); yield return(UtilityOwn.Yield.WaitForEndOfFrame); if (targetObject == null) { Debug.LogError("load asset failed:" + assetPath); yield break; } var objRenderers = targetObject.GetComponentsInChildren <Renderer>(true); var objMaterials = new HashSet <Material>(); foreach (var r in objRenderers) { foreach (var mat in r.sharedMaterials) { objMaterials.Add(mat); } if (r is MeshRenderer) { var mr = r as MeshRenderer; var mesh = mr.GetComponent <MeshFilter>().sharedMesh; if (mesh) { mTempReport.meshVertexCount += mesh.vertexCount; mTempReport.meshTriangleCount += mesh.triangles.Length / 3; } } else if (r is SkinnedMeshRenderer) { var smr = r as SkinnedMeshRenderer; var mesh = smr.sharedMesh; if (mesh) { mTempReport.meshVertexCount += smr.sharedMesh.vertexCount; mTempReport.meshTriangleCount += smr.sharedMesh.triangles.Length / 3; } } else if (r is ParticleSystemRenderer) { var psr = r as ParticleSystemRenderer; var mesh = psr.mesh; if (mesh) { mTempReport.meshVertexCount += mesh.vertexCount; mTempReport.meshTriangleCount += mesh.triangles.Length / 3; } } } mTempReport.rendererCount = objRenderers.Length; mTempReport.materialCount = objMaterials.Count; mTempReport.particleSystemCount = targetObject.GetComponentsInChildren <ParticleSystem>(true).Length; mTempReport.animationCount = targetObject.GetComponentsInChildren <Animation>(true).Length; mTempReport.animatorCount = targetObject.GetComponentsInChildren <Animator>(true).Length; yield return(UtilityOwn.Yield.WaitForEndOfFrame); yield return(UtilityOwn.Yield.WaitForEndOfFrame); t2 = Time.realtimeSinceStartup; //实例化 var instList = new List <GameObject>(); for (int i = 0; i < instantiateCountForEach; i++) { GameObject go = Instantiate(targetObject); go.transform.position = Vector3.zero; instList.Add(go); } float t3 = Time.realtimeSinceStartup; mTempReport.instTime = (t3 - t2) * 1000f / instantiateCountForEach; //渲染 ParticleSystem[] psOfOneInst = instList[0].GetComponentsInChildren <ParticleSystem>(true); yield return(UtilityOwn.Yield.WaitForEndOfFrame); yield return(UtilityOwn.Yield.WaitForEndOfFrame); yield return(UtilityOwn.Yield.WaitForEndOfFrame); float t4 = Time.realtimeSinceStartup; mTempReport.frameTimeMin = float.MaxValue; mTempReport.frameTimeMax = float.MinValue; int frame = 0; List <float> frameTimeList = new List <float>(); while (Time.realtimeSinceStartup - t4 < testTimeForEach) { var dtMs = Time.deltaTime * 1000; frame++; mTempReport.frameTimeMin = Math.Min(mTempReport.frameTimeMin, dtMs); mTempReport.frameTimeMax = Math.Max(mTempReport.frameTimeMax, dtMs); frameTimeList.Add(dtMs); int particleCount = 0; for (int i = 0; i < psOfOneInst.Length; ++i) { particleCount += psOfOneInst[i].particleCount; } if (mTempReport.particleAliveCountMax < particleCount) { mTempReport.particleAliveCountMax = particleCount; } yield return(UtilityOwn.Yield.WaitForEndOfFrame); } mTempReport.frameTimeMin = mTempReport.frameTimeMin / instantiateCountForEach - baseFrameTime; mTempReport.frameTimeMax = mTempReport.frameTimeMax / instantiateCountForEach - baseFrameTime; frameTimeList.Sort(); frameTimeList.Reverse(); float avg = 0f; int topX = Math.Min(topFrameCount, frameTimeList.Count); for (int i = 0; i < topX; ++i) { avg += frameTimeList[i]; } mTempReport.frameTimeAvgTopX = avg / topX / instantiateCountForEach - baseFrameTime; if (topX < topFrameCount) { Debug.LogWarning("frame count lower than expectation:" + assetPath); } //统计纹理信息 yield return(UtilityOwn.Yield.WaitForEndOfFrame); mTempReport.textureInfoDetails = new Dictionary <IntPtr, TextureInfo>(); var texSamples = GetTextureMemorySamples(); foreach (var t in texSamples) { if (mInitTextureSamples.ContainsKey(t.Key) == false) { mTempReport.textureInfoDetails.Add(t.Key, t.Value); mTempReport.texMemKBytes += t.Value.Bytes; mTempReport.texMemCount++; } } //清理 foreach (var obj in instList) { UnityEngine.Object.DestroyImmediate(obj); } instList.Clear(); texSamples.Clear(); } yield return(FullUnloadAndGC()); }