Unity3D研究院编辑器之ManagedStaticReferences()静态引用(二十九)

Unity3D研究院编辑器之ManagedStaticReferences()静态引用(二十九)

https://www.xuanyusong.com/archives/4390

Unity3D研究院编辑器之ManagedStaticReferences()静态引用(二十九)

雨松MOMO 【Unity3D拓展编辑器】 围观162784 条评论 编辑日期:2017-05-30 字体:大 中 小

Unity的Profiler可以看出来内存,但是遇到ManagedStaticReferences()估计大家都跪了。因为这个资源被静态引用了,然后我们并不知道它被哪里静态引用了。

我想了个办法,可以通过反射来查询它。先讲一下原理

1.反射dll

2.遍历所有的.cs 取出所有带static的属性。

3.对static下的所有属性以及子属性进行深度遍历,最终即可得出来被静态引用的资源。

如下代码所示,运行环境unity5.2.2

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

using System.Collections;

using System.Collections.Generic;

using UnityEngine;

using UnityEditor;

using System.Reflection;

using System;

using System.Text;

 

public partial class ReportAsset{

 

[MenuItem("Tools/Report/脚本Static引用")]

static void StaticRef ()

{

//静态引用

LoadAssembly ("Assembly-CSharp-firstpass");

LoadAssembly ("Assembly-CSharp");

 

}

 

static void LoadAssembly(string name)

{

Assembly assembly = null;

try {

assembly = Assembly.Load(name);

}

catch (Exception ex) {

Debug.LogWarning (ex.Message);

}

finally{

if (assembly != null) {

foreach (Type type in assembly.GetTypes()) {

try {

HashSet<string> assetPaths = new HashSet<string>();

FieldInfo[] listFieldInfo = type.GetFields (BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public);  

foreach (FieldInfo fieldInfo in listFieldInfo) {

if (!fieldInfo.FieldType.IsValueType) {

SearchProperties (fieldInfo.GetValue (null),assetPaths);

}

}

if (assetPaths.Count > 0) {

StringBuilder sb = new StringBuilder ();

sb.AppendFormat ("{0}.cs\n", type.ToString ());

foreach (string path in assetPaths) {

sb.AppendFormat ("\t{0}\n", path);

}

Debug.LogError (sb.ToString ());

}

 

} catch(Exception ex){

Debug.LogWarning (ex.Message);

}

}

}

}

}

 

static HashSet<string> SearchProperties(object obj,HashSet<string> assetPaths)

{    

if (obj != null) {

if (obj is UnityEngine.Object) {

UnityEngine.Object[]depen = EditorUtility.CollectDependencies (new UnityEngine.Object[]{ obj as UnityEngine.Object });

foreach (var item in depen) {

string assetPath = AssetDatabase.GetAssetPath (item);

if (!string.IsNullOrEmpty (assetPath)) {

if (!assetPaths.Contains (assetPath)) {

assetPaths.Add (assetPath);

}

}

}

} else if (obj is IEnumerable) {

foreach (object child in (obj as IEnumerable)) {

SearchProperties (child,assetPaths);

}

}else if (obj is System.Object) {

if (!obj.GetType ().IsValueType) {

FieldInfo[] fieldInfos = obj.GetType ().GetFields ();

foreach (FieldInfo fieldInfo in fieldInfos) {

object o = fieldInfo.GetValue (obj);

if (o != obj) {

SearchProperties (fieldInfo.GetValue (obj),assetPaths);

}

}

}

}

}

return assetPaths;

}

 

}

如下图所示,静态引用已经查出来了。
Unity3D研究院编辑器之ManagedStaticReferences()静态引用(二十九) - 雨松MOMO程序研究院 - 1

问题:

1.这个脚本查不出lua里的静态引用。lua可以遍历G里的所有table表,和上面执行类型的操作就可以查出来。

2.如果想定向查询,比如专门查某一个资源在内存中哪里被引用,也和上面算法差不多改改就可以。

3.Unity在Editor下的Profiler其实是非常不准确的,因为自己在Project视图中选择一些资源unity也会记录在Profiler中,并且没办法完全清除。如果想测试内存,可以打一个pc包在连上Profiler在看即可。

最后,如果大家有更好的方法,欢迎再下面给我留言,我们一起讨论~

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值