最近线上Kibana收集到报错:
UnityEngine.EventSystems.UIBehaviour.IsActive ()
UnityEngine.UI.Graphic.SetVerticesDirty ()
UnityEngine.UI.Text.set_text (System.String value)
还有:
UnityEngine.EventSystems.UIBehaviour.IsActive ()
UnityEngine.UI.Graphic.SetVerticesDirty ()
UnityEngine.UI.Graphic.set_color (Color value)
当然这两个底层是一样的,根据Stack分析一下:
public virtual string text
{
get
{
return this.m_Text;
}
set
{
if (string.IsNullOrEmpty(value))
{
if (string.IsNullOrEmpty(this.m_Text))
{
return;
}
this.m_Text = string.Empty;
this.SetVerticesDirty();
}
else if (this.m_Text != value)
{
this.m_Text = value;
this.SetVerticesDirty();
this.SetLayoutDirty();
}
}
}
跳转:
public virtual void SetVerticesDirty()
{
if (!this.IsActive())
{
return;
}
this.m_VertsDirty = true;
CanvasUpdateRegistry.RegisterCanvasElementForGraphicRebuild(this);
if (this.m_OnDirtyVertsCallback != null)
{
this.m_OnDirtyVertsCallback();
}
}
跳转:
public virtual bool IsActive()
{
return base.isActiveAndEnabled;
}
再跳:
public extern bool isActiveAndEnabled
{
[WrapperlessIcall]
[MethodImpl(MethodImplOptions.InternalCall)]
get;
}
查了一下:
isActiveAndEnabled:Whats the difference between Behaviour.isActiveAndEnabled and Behaviour.enabled?
回答:
Active is the state of GameObject . Enabled is the state of Component. IsActiveAndEnabled checks both.
OK,到这里,基本上已经可以确定,是GameObject或Component为空。为什么会这样,看了一下代码,看到了Loom的QueueOnMainThread(Action action, float time),这个函数在多线程中延迟一段时间,然后再跳会到主线程执行action,其中time是延迟执行,action里对UGUI的text.text和image.color进行了赋值,完全符合上边的报错信息,问题基本定位。
当然,其实项目中这样的问题还有不少,其实这个问题引申一下,凡是延迟多少秒执行的操作都要注意引用是否还存在,尤其是委托泛滥的代码里。
总结了一下,可能会出这个问题的几个情景:
1.脚本A协程延迟引用已被销毁的脚本B变量;
2.DontDestroy脚本引用已被销毁的脚本变量;
3.异步延迟引用已被销毁的脚本变量。
所以注意:
1.尽量不要这么写,很不好;
2.如果一定要这么写,记得要做非空判断。