【Unity填坑日记】UGUI崩溃巨坑:UI::CanvasRenderer::SyncDirtyElements

在使用UGUI的项目中经常遇到诸如

0x0000000140044A66 (Unity) Unity::GameObject::IsActive
0x00000001411B2E73 (Unity) UI::CanvasRenderer::SyncDirtyElements
0x00000001411BFAC9 (Unity) UI::CanvasManager::UpdateDirtyRenderers
0x00000001411BD336 (Unity) UI::Canvas::UpdateBatches
0x00000001411BE11C (Unity) UI::CanvasManager::WillRenderCanvases
0x00000001403B6C8C (Unity) PlayerLoop
0x0000000140B98C3C (Unity) Application::UpdateScene
0x0000000140B9A6F9 (Unity) Application::UpdateSceneIfNeeded
0x0000000140BA0C84 (Unity) Application::TickTimer
0x0000000140DD1197 (Unity) RelaunchUnity
0x0000000140DD277B (Unity) WinMain
0x00000001414EB994 (Unity) read
0x00000000778B59BD (kernel32) BaseThreadInitThunk

的错误,而且最要命的是,一般不在Editor上出现,一般是在iOS、ANDROID真机上小概率随机出现。而一出现就直接游戏崩溃,一发入魂。。

这个问题从unity5.1开始一直困扰到5.3.5p3都没有得到彻底解决,在更新到5.3.5p3后发现该问题居然能在editor出现了。于是花了一整晚时间找这个原因……

根据unity的出错信息,大概猜测是死在了render一个已经销毁的UI element

通过检查代码,发现我们的一个清空Transform下所有子物体的写法如下:

public static void DestroyChildren(Transform transform) {
    int childCount = transform.childCount;
    for (int i = childCount - 1; i >= 0; --i) {
        var go = transform.GetChild(i).gameObject;
        GameObject.Destroy(go); 
    }
    transform.DetachChildren();
}

怀疑是Destroy后,Unity存在一个BUG导致CanvasRenderer还继续访问了该物体(已经为NULL)

修改代码如下后,问题解决

    public static void DestroyChildren(Transform transform) {
        int childCount = transform.childCount;
        for (int i = childCount - 1; i >= 0; --i) {
            var go = transform.GetChild(i).gameObject;
            go.SetActive(false);

            //by CG:如果不延迟释放,则会crash:UNITY BUG:UI::CanvasRenderer::SyncDirtyElements
            GameObject.Destroy(go, 0.3f); 
        }
        transform.DetachChildren();
    }

我只能说……此处太坑……

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值