Unity查找unity 脚本和场景关联被哪些Perfab或场景引用

努力加载中,稍等...
暂无新消息
努力加载中,稍等...
已无更多消息...
这些人最近关注了你
努力加载中,稍等...
已无更多消息
努力加载中,稍等...
已无更多消息
WinDbg查看Unity C#脚本堆栈
版权所有,禁止匿名转载;禁止商业使用;禁止个人使用。
最近项目遇到了两次卡死的问题,一次是因为场景里的未正确设置导致脚本里碰撞检测的代码进入了死循环,另一次也是因为循环跳出条件判断不严谨。里找到这类问题的原因并不简单,因为卡死既有可能发生在脚本层,也有可能发生在层。使用或到卡死进程上,只能看到脚本层的堆栈,若卡死发生在层则什么也看不到;使用虽能看到全部堆栈,但中间脚本层的托管代码调用堆栈仅是一堆没有符号的地址也很难看出问题,如下图。相比的调试功能更为强大,因此本文探索了在中查看脚本堆栈的方法。考虑到是遵循跨平台的,的实现可能和的差别不大,我们首先尝试了里调试托管代码的方法——使用调试扩展。然而通过列出加载模块我们发现进程并未加载,而是加载了,因此这种方法不行。再考虑到上地址与符号的匹配是通过文件实现的,于是想找到编译生成的脚本的文件,但我们在目录下只能找到文件。这是因为将文件格式转为了自己的文件格式,支持使用外部的编译器来编译脚本并导入工程,但若要支持调试还需要通过提供的来将转成的调试符号信息,参考:。以上方法不行只能从本身入手了。我们从官方文档的一节中找到了一些信息:使用调试脚本时是调用了本身的一个导出函数来获取给定地址处的函数名,这个导出函数名为(或)。那么的版本是否也存在一个这样的导出函数呢?通过我们发现是存在的,并且和是同一函数。既然导出函数存在,接下来要考虑如何调用它。通过分析可以得出的函数原型应该是,而的命令可以让目标进程执行一个函数,我们尝试了一下,如下图。这是因为仅提供了自身的,而未提供的文件,导致无法判断的函数原型,也就无法生成要执行的指令序了。既然我们已经分析出它的函数原型,那就我们自己处理吧:)将参数(待获取函数名的地址)压栈)将返回地址压栈(执行完我们要求插入执行的后要将执行绪还给原流程))对当前下断(用于查看执行完后的返回结果),然后将改为)继续运行,断下后恢复堆栈,查看返回结果我们用封装一下:执行:对比测试源码,可以看到能正确反应问题所在了:
下载次数:0
分类:(原创)Unity3D圈
登录后参与讨论。点击
请勿发表无意义的内容请勿发表重复内容请勿发表交易类内容禁止发表广告宣传贴请使用文明用语其它
淫秽色情政治倾向人身攻击抄袭剽窃广告刷屏恶意挖坟冒充他人其它程序写累了,就来玩玩酷跑小游戏吧,嘿嘿。
雨松MOMO送你一首歌曲,嘿嘿。
Unity3D研究院之查找资源被哪里引用了
Unity3D研究院之查找资源被哪里引用了
围观10689次
编辑日期: 字体:
Unity提供了一个方法 AssetDatabase.GetDependencies(),但是它只能查找这个资源引用了那些资源。 但是我想要的是查找某个资源被那些资源引用了,这是两种相反的查找公式。 其实网上也有很多这样的插件了,似乎代码量都太多了。昨天晚上加班时脑洞打开,想到了一个简单的方法。通过GUID全局搜索匹配。。几行代码就能搞定~~
如下图所示,右键随便选择一个资源,点击 Find References。
然后开始匹配资源。
匹配结束后会把匹配到的资源Log出来。以下代码直接放到你的工程里就可以直接用。
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061
using UnityEngine;using System.Collections;using UnityEditor;using System.IO;using System.Linq;using System.Text;using System.Text.RegularExpressions;using System.Collections.Generic;&public class FindReferences{&&&&&&[MenuItem("Assets/Find References", false, 10)]&&&&static private void Find()&&&&{&&&&&&&&EditorSettings.serializationMode = SerializationMode.ForceText;&&&&&&&&string path = AssetDatabase.GetAssetPath(Selection.activeObject);&&&&&&&&if (!string.IsNullOrEmpty(path))&&&&&&&&{&&&&&&&&&&&&string guid = AssetDatabase.AssetPathToGUID(path);&&&&&&&&&&&&List withoutExtensions = new List(){".prefab",".unity",".mat",".asset"};&&&&&&&&&&&&string[] files = Directory.GetFiles(Application.dataPath, "*.*", SearchOption.AllDirectories)&&&&&&&&&&&&&&&&.Where(s =& withoutExtensions.Contains(Path.GetExtension(s).ToLower())).ToArray();&&&&&&&&&&&&int startIndex = 0;&&&&&&&&&&&&&EditorApplication.update = delegate()&&&&&&&&&&&&{&&&&&&&&&&&&&&&&string file = files[startIndex];&&&&&&&&&&&&&&&&&&&&&&&&&&&& bool isCancel = EditorUtility.DisplayCancelableProgressBar("匹配资源中", file, (float)startIndex / (float)files.Length);&&&&&&&&&&&&&&&&&if (Regex.IsMatch(File.ReadAllText(file), guid))&&&&&&&&&&&&&&&&{&&&&&&&&&&&&&&&&&&&&Debug.Log(file, AssetDatabase.LoadAssetAtPath&Object&(GetRelativeAssetsPath(file)));&&&&&&&&&&&&&&&&}&&&&&&&&&&&&&&&&&startIndex++;&&&&&&&&&&&&&&&&if (isCancel || startIndex &= files.Length)&&&&&&&&&&&&&&&&{&&&&&&&&&&&&&&&&&&&&EditorUtility.ClearProgressBar();&&&&&&&&&&&&&&&&&&&&EditorApplication.update = null;&&&&&&&&&&&&&&&&&&&&startIndex = 0;&&&&&&&&&&&&&&&&&&&&Debug.Log("匹配结束");&&&&&&&&&&&&&&&&}&&&&&&&&&&&&&};&&&&&&&&}&&&&}&&&&&[MenuItem("Assets/Find References", true)]&&&&static private bool VFind()&&&&{&&&&&&&&string path = AssetDatabase.GetAssetPath(Selection.activeObject);&&&&&&&&return (!string.IsNullOrEmpty(path));&&&&}&&&&&static private string GetRelativeAssetsPath(string path)&&&&{&&&&&&&&return "Assets" + Path.GetFullPath(path).Replace(Path.GetFullPath(Application.dataPath), "").Replace('\\', '/');&&&&}}
美中不足的地方就是查找速度了。。其实正则表达式匹配的速度还是很快,慢的地方是File.ReadAllText(file) 如果大家有更好的办法,欢迎推荐~
今天我无意发现了一个更快的方法,可惜只能在mac上用。比我上面的方法要快N倍啊,快的丧心病狂啊~欢迎大家用啊~~。。。
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364
using UnityEngine;using System.Collections;using UnityEditor;using System.Collections.Generic;&public class FindProject {
#if UNITY_EDITOR_OSX
[MenuItem("Assets/Find References In Project", false, 2000)] private static void FindProjectReferences() {
string appDataPath = Application.dataPath;
string output = "";
string selectedAssetPath = AssetDatabase.GetAssetPath (Selection.activeObject);
List&string& references = new List&string&();
string guid = AssetDatabase.AssetPathToGUID (selectedAssetPath);
var psi = new System.Diagnostics.ProcessStartInfo();
psi.WindowStyle = System.Diagnostics.ProcessWindowStyle.Maximized;
psi.FileName = "/usr/bin/mdfind";
psi.Arguments = "-onlyin " + Application.dataPath + " " + guid;
psi.UseShellExecute = false;
psi.RedirectStandardOutput = true;
psi.RedirectStandardError = true;
System.Diagnostics.Process process = new System.Diagnostics.Process();
process.StartInfo = psi;
process.OutputDataReceived += (sender, e) =& {
if(string.IsNullOrEmpty(e.Data))
string relativePath = "Assets" + e.Data.Replace(appDataPath, "");
// skip the meta file of whatever we have selected
if(relativePath == selectedAssetPath + ".meta")
references.Add(relativePath);
process.ErrorDataReceived += (sender, e) =& {
if(string.IsNullOrEmpty(e.Data))
output += "Error: " + e.Data + "\n";
process.Start();
process.BeginOutputReadLine();
process.BeginErrorReadLine();
process.WaitForExit(2000);
foreach(var file in references){
output += file + "\n";
Debug.Log(file, AssetDatabase.LoadMainAssetAtPath(file));
Debug.LogWarning(references.Count + " references found for object " + Selection.activeObject.name + "\n\n" + output); }
本文固定链接:
转载请注明:
雨松MOMO提醒您:亲,如果您觉得本文不错,快快将这篇文章分享出去吧 。另外请点击网站顶部彩色广告或者捐赠支持本站发展,谢谢!
作者:雨松MOMO
专注移动互联网,Unity3D游戏开发
如果您愿意花10块钱请我喝一杯咖啡的话,请用手机扫描二维码即可通过支付宝直接向我捐款哦。
您可能还会对这些文章感兴趣!Unity内存管理
资源加载方式有三种
1.&静态引用
&建一个public的变量,在Inspector里把prefab拉上去,用的时候instantiate
2. 如何卸载Resources.Load()方式加载的资源,(Load以后instantiate)
Object obj = Resources.Load("MyPrefab");
GameObject instance = Instantiate(obj) as GameO
Destroy(instance); //&销毁了一个Prefab实例,这时候
MyPrefab已经没有被实际的物体引用了
让变量obj不再引用MyPrefab
Resources.UnloadUnusedAssets();//释放已经没有引用的Asset
(这个API非常耗时,强烈建议不要在关卡内部调用)
3.&如何卸载AssetBundle.Load()方式加载的资源,(Load以后instantiate)
AssetBundle AssetBundle1 =
AssetBundle.CreateFromFile("1.unity3d");//存放于“镜像内存”中
obj1.renderer.material.mainTexture = AssetBundle1.Load("wall") as
T//存放于“主内存”中
//&obj2与obj1指向同一个Texture
obj2.renderer.material.mainTexture =
obj1.renderer.material.mainT
如果AssetBundle1.Unload(true);那obj1和obj2都变成黑的了,因为指向的Texture
//&关闭AssetBundle但没有摧毁创建的对象和引用
如果AssetBundle.Unload(false);&那obj1和obj2不变,只是释放AssetBundle1的内存镜像
Destroy(obj1);//obj1被释放,但并不会释放刚才Load的Texture
Resources.UnloadUnusedAssets();//不会有任何内存释放
因为Texture asset还被obj2用着
Destroy(obj2);//obj2被释放,但也不会释放刚才Load的Texture
Resources.UnloadUnusedAssets();//这时候刚才load的Texture
Asset释放了,因为没有任何引用了
GC.Collect(); //&强制立即释放内存
用AssetBundle加载的asset一样可以用Resources.UnloadUnusedAssets卸载,但必须先AssetBundle.Unload,才会被识别为无用的asset
4. 场景切换
自动销毁:
所有的内存对象都会被自动销毁,包括你用AssetBundle.Load加载的对象和Instaniate克隆的。
b.&Unity在一个场景开始时,根据场景构成和引用关系所自动读取的资源,只有在读取一个新的场景或者reset当前场景时,才会得到清理。
&&不自动销毁:
AssetBundle文件自身的内存镜像,那个必须要用Unload来释放,用.net的术语,这种数据缓存是非托管的。
b.&在场景之间被保持的脚本(通常这些脚本所挂载的GameObject,作为了DontDestroyOnLoad函数的参数,即被其标识为场景切换时不失效),且这些脚本很可能含有对其他物体的Component或者资源的引用,这些资源就都得不到释放。
c.&static的单例(singleton)在场景切换时也不会被摧毁,如果这种单例含有大量的对资源的引用,也会成为大问题。
5.&a.&Load的是Asset,
销毁时:Load的Asset要Unload
&Instantiate的是GameObject和Object in
Scene,销毁时:&Instantiate的或者new的object可以Destroy
&Texture加载以后是到内存,显示的时候才进入显存的Texture
三种加载方式的区别:
静态引用 + Resouces.load()
引用对象texture是在instantiate时加载,&第一次instantiate时会包含加载引用
assets的操作,导致第一次加载的延迟
assetBundle.Load()
会把perfab的全部assets 都加载,instantiate时只是生成Clone
a. Destroy:
主要用于销毁克隆对象,也可以用于场景内的静态物体,不会自动释放该对象的所有引用。虽然也可以用于Asset,但是概念不一样要小心,如果用于销毁从文
件加载的Asset对象会销毁相应的资源文件!但是如果销毁的Asset是Copy的或者用脚本动态生成的,只会销毁内存对象。
&&你Load出来的Assets其实就是个数据源,用于生成新对象或者被引用,生成的过程可能是复制(clone)也可能是引用(指针)
& &当你Destroy一个实例时,只是释放那些Clone(复制)对象,并不会释放引用对象和Clone的数据源对象,Destroy并不知道是否还有别的object在引用那些对象。
& & 等到没有任何
游戏场景物体在用这些Assets以后,这些assets就成了没有引用的游离数据块了,是UnusedAssets了,这时候就可以通过&Resources.UnloadUnusedAssets来释放。
AssetBundle.Unload(false):释放AssetBundle文件内存镜像
AssetBundle.Unload(true):释放AssetBundle文件内存镜像同时销毁所有已经Load的Assets内存对象
Reources.UnloadAsset(Object):显式的释放已加载的Asset对象,只能卸载磁盘文件加载的Asset对象
Resources.UnloadUnusedAssets:用于释放所有没有引用的Asset对象
f. &GC.Collect()强制垃圾收集器立即释放内存
本文摘自:
已投稿到:
以上网友发言只代表其个人观点,不代表新浪网的观点或立场。

我要回帖

更多关于 unity perfab 的文章

 

随机推荐