解决在Unity中封装Debug.Log后代码行定位问题

 

解决在Unity中封装Debug.Log后代码行定位问题

众所周知,代码中使用Debug.Log*输出的日志在Unity的ConsoleWindow中可以双击定位到对应的代码行,然而将Debug.Log*封装到自己的日志类中后,定位就失去意义了。原因很简单,Unity只会处理StackFrame的栈顶信息,它们保存在LogEntry中,栈顶的方法对应的脚本文件会以其instanceID来保存,其他StackTrace信息则以字符串结果存储,最终在双击ConsoleWindow中的ListView条目时通过指定了OnOpenAssetAttribute的callback来打开代码编辑器。其中,OnOpenAssetAttribute参数用于处理存在多个Callback时的优先级问题。

image

通过阅读ConsoleWindow代码,想到了一个解决思路:自己实现OnOpenAsset,通过获取ConsoleWindow中的ListView得到当前选中的row,然后在LogEntries中取得该行对应的LogEntry,其中的condition字段保存了StackTrace字符串,最后过滤掉包装的日志类后拿到脚本文件名和代码行,用OpenFileAtLineExternal直接打开。在实现过程中发现,完全没有必要拿到LogEntry,因为ConsoleWindow中的m_ActiveText就是StackTrace字符串,直接处理就好了。

在想到该方案之前,看过两个解决方法:1)将日志类编译成DLL;2)输出日志时自己记录StackFrame,通过一系列手段在OnOpenAsset查找LogEntry中对应的StackFrame。不过这两种方案都不能满足个人的完美主义情节,方案1失去了预编译宏的灵活,一旦日志系统改动需要重编DLL和处理依赖,方案2低效且过于复杂。

最后摘出代码供参考,实现环境为:Unity 4.7.5f1, UnityVS+Visual Studio 2015 Pro

 

众所周知,代码中使用Debug.Log*输出的日志在Unity的ConsoleWindow中可以双击定位到对应的代码行,然而将Debug.Log*封装到自己的日志类中后,定位就失去意义了。原因很简单,Unity只会处理StackFrame的栈顶信息,它们保存在LogEntry中,栈顶的方法对应的脚本文件会以其instanceID来保存,其他StackTrace信息则以字符串结果存储,最终在双击ConsoleWindow中的ListView条目时通过指定了OnOpenAssetAttribute的callback来打开代码编辑器。其中,OnOpenAssetAttribute参数用于处理存在多个Callback时的优先级问题。

image

通过阅读ConsoleWindow代码,想到了一个解决思路:自己实现OnOpenAsset,通过获取ConsoleWindow中的ListView得到当前选中的row,然后在LogEntries中取得该行对应的LogEntry,其中的condition字段保存了StackTrace字符串,最后过滤掉包装的日志类后拿到脚本文件名和代码行,用OpenFileAtLineExternal直接打开。在实现过程中发现,完全没有必要拿到LogEntry,因为ConsoleWindow中的m_ActiveText就是StackTrace字符串,直接处理就好了。

在想到该方案之前,看过两个解决方法:1)将日志类编译成DLL;2)输出日志时自己记录StackFrame,通过一系列手段在OnOpenAsset查找LogEntry中对应的StackFrame。不过这两种方案都不能满足个人的完美主义情节,方案1失去了预编译宏的灵活,一旦日志系统改动需要重编DLL和处理依赖,方案2低效且过于复杂。

最后摘出代码供参考,实现环境为:Unity 4.7.5f1, UnityVS+Visual Studio 2015 Pro

 

  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是一个Unity 2021版本封装的获取网络图片并转换成Sprite的代码示例: ```c# using System.Collections; using UnityEngine; using UnityEngine.Networking; using UnityEngine.UI; public class ImageDownloader : MonoBehaviour { // 下载图片并转换成Sprite的方法 public IEnumerator DownloadImage(string url, Image image) { // 创建UnityWebRequest对象 UnityWebRequest request = UnityWebRequestTexture.GetTexture(url); // 发送请求并等待返回结果 yield return request.SendWebRequest(); // 判断请求是否出错 if (request.result != UnityWebRequest.Result.Success) { Debug.LogError("Failed to download image: " + request.error); yield break; } // 获取Texture2D对象 Texture2D texture = ((DownloadHandlerTexture)request.downloadHandler).texture; // 创建Sprite Sprite sprite = Sprite.Create(texture, new Rect(0, 0, texture.width, texture.height), Vector2.zero); // 设置Image组件的Sprite image.sprite = sprite; } } ``` 这个代码示例,我们创建了一个名为ImageDownloader的类,其包含一个用于下载网络图片并转换成Sprite的协程方法DownloadImage。该方法接受两个参数:图片的URL和一个Image组件,用于显示下载后的Sprite。方法,我们首先创建了一个UnityWebRequest对象,然后使用它发送请求并等待返回结果。如果请求出错,我们将在控制台输出错误信息并退出方法。如果请求成功,我们获取到了Texture2D对象,然后使用它创建一个新的Sprite对象。最后,我们将创建的Sprite对象设置为Image组件的Sprite,完成图片下载和转换的过程。 在使用该方法时,你可以在其他脚本创建一个ImageDownloader对象,并调用DownloadImage方法来获取网络图片并将其显示在UI界面上。比如: ```c# using UnityEngine; using UnityEngine.UI; public class MyScript : MonoBehaviour { public Image image; public string url; // 创建ImageDownloader对象 private ImageDownloader imageDownloader = new ImageDownloader(); void Start() { // 调用DownloadImage方法 StartCoroutine(imageDownloader.DownloadImage(url, image)); } } ``` 在这个示例代码,我们在MyScript脚本创建了一个Image组件和一个字符串变量url,用于存储图片的URL。然后,在Start方法,我们创建了一个ImageDownloader对象,并调用了它的DownloadImage方法,将url和image组件作为参数传递进去。通过这样的方式,我们可以轻松地将网络图片下载并显示在UI界面上。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值