当前位置: 首页 > 游戏攻略> 正文

Unity协程问题及解决方案

来源:网络 作者:趣玩小编 发布时间:2024-05-12 16:01:29

现如今,Unity中的协程(Coroutine)方案已显得老旧,而Unitask等异步方案可以直接解决如异常捕获等各类问题。此外,Unity官方也在开发一套异步方案,但目前仍需要在协程这个方案上继续琢磨。

Unity协程中无法输出完整的栈跟踪,因为协程编译后会转换为IL编码的状态机,中间存在栈回到堆的过程。因此,在有多个yield函数嵌套的协程中出现报错时,栈信息会是缺失的,仅显示“栈信息丢失”。为了更好地解决这个问题,需要重新封装MoveNext()或采用Unitask。然而,这样做会增加代码的复杂度。经过摸索后,发现还存在一些可行的途径。

1. StackTrace类打印栈跟踪

使用StackTrace类可以得到当前执行栈的相关信息,通过接口GetFrame可以得到当前哪一层调用的相关信息。然而,由于协程会在编译后转换为状态机,所以无法获取完整的栈信息。

抖个机灵,如果在非yield语句中进行常规代码的调用或函数调用,则可正常拿到类名和代码行数。
打印:
14
19
24

下面将基于这个思路继续扩展。

2. StackTrace封装

2.1 Begin/End 语句块

下一步,创建一个名为CoroutineHelper的类,用于存放协程的相关扩展。在类中添加一个栈对象,保存每一步的栈跟踪信息。值得注意的是,没有直接使用C#自带的Stack,因为无法逆序遍历不方便输出栈日志,因此直接采用数组实现。

若这样的话,每一步协程函数跳转都要用Begin、End语句包装又太丑。

2.2 使用扩展方法与using语法糖优化

实际上非yield语句,普通函数调用也是可以的,编译后不会被转换。因此可用扩展方法进行优化。

这样调用时就舒服多了,对原始代码的改动也最小。

不过还需要处理函数结束时调用Pop方法,这个可以结合using语法糖使用。

最终调用时如下:

3. 打印输出

通过StackTrace类以及语法糖处理,可以拿到完整栈信息后,还需要打印输出。可以加入Unity编辑器下IDE链接的语法,这样打印日志直接具有超链接效果。

最终效果如下:

4. 源码

最后提供下这部分功能源码。

相关攻略 更多 +
玩家最喜欢 更多 +
热门攻略 更多 +
热搜
查看完整榜单