源战役客户端
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

127 rivejä
4.3 KiB

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using MemoryProfilerWindow;
using UnityEditor.MemoryProfiler;
using UnityEngine;
namespace MemoryProfilerWindow
{
class ShortestPathToRootFinder
{
private readonly CrawledMemorySnapshot _snapshot;
public ShortestPathToRootFinder(CrawledMemorySnapshot snapshot)
{
_snapshot = snapshot;
}
public ThingInMemory[] FindFor(ThingInMemory thing)
{
var seen = new HashSet<ThingInMemory>();
var queue = new Queue<List<ThingInMemory>>();
queue.Enqueue(new List<ThingInMemory> { thing});
while (queue.Any())
{
var pop = queue.Dequeue();
var tip = pop.Last();
string reason;
if (IsRoot(tip, out reason))
return pop.ToArray();
foreach (var next in tip.referencedBy)
{
if (seen.Contains(next))
continue;
seen.Add(next);
var dupe = new List<ThingInMemory>(pop) {next};
queue.Enqueue(dupe);
}
}
return null;
}
public bool IsRoot(ThingInMemory thing, out string reason)
{
reason = null;
if (thing is StaticFields)
{
reason = "Static fields are global variables. Anything they reference will not be unloaded.";
return true;
}
if (thing is ManagedObject)
return false;
if (thing is GCHandle)
return false;
var nativeObject = thing as NativeUnityEngineObject;
if (nativeObject == null)
throw new ArgumentException("Unknown type: " + thing.GetType());
if (nativeObject.isManager)
{
reason = "this is an internal unity'manager' style object, which is a global object that will never be unloaded";
return true;
}
if (nativeObject.isDontDestroyOnLoad)
{
reason = "DontDestroyOnLoad() was called on this object, so it will never be unloaded";
return true;
}
if ((nativeObject.hideFlags & HideFlags.DontUnloadUnusedAsset) != 0)
{
reason = "the DontUnloadUnusedAsset hideflag is set on this object. Unity's builtin resources set this flag. Users can also set the flag themselves";
return true;
}
if (nativeObject.isPersistent)
return false;
if (IsComponent(nativeObject.classID))
{
reason = "this is a component, living on a gameobject, that is either part of the loaded scene, or was generated by script. It will be unloaded on next scene load.";
return true;
}
if (IsGameObject(nativeObject.classID))
{
reason = "this is a gameobject, that is either part of the loaded scene, or was generated by script. It will be unloaded on next scene load if nobody is referencing it";
return true;
}
if (IsAssetBundle(nativeObject.classID))
{
reason = "this object is an assetbundle, which is never unloaded automatically, but only through an explicit .Unload() call.";
return true;
}
reason = "This object is a root, but the memory profiler UI does not yet understand why";
return true;
}
private bool IsGameObject(int classID)
{
return _snapshot.nativeTypes[classID].name == "GameObject";
}
private bool IsAssetBundle(int classID)
{
return _snapshot.nativeTypes[classID].name == "AssetBundle";
}
private bool IsComponent(int classID)
{
var packedNativeType = _snapshot.nativeTypes[classID];
if (packedNativeType.name == "Component")
return true;
var baseClassID = packedNativeType.nativeBaseTypeArrayIndex;
return baseClassID != -1 && IsComponent(baseClassID);
}
}
}