I am working with Unity3D's GUI system and have created a wrapper around the GUI methods (like GUI.Label(), in this case). However, my question is actually a general C# question.
Here is my GuiLabel class which wraps the functionality of Unity's GUI.Label
method and also subscribes to an event of the singleton LanguageManager.Instance
.
public sealed class GuiLabel : GuiElementBase
{
#region private and protected variables
protected string m_langMgrKey;
protected GUIStyle m_style;
protected string m_text;
#endregion
public GuiLabel(Rect rect, string langMgrKey, GUIStyle style) : base(rect)
{
m_langMgrKey = langMgrKey;
m_style = style;
m_text = LanguageManager.Instance.GetTextValue(m_langMgrKey);
LanguageManager.Instance.OnChangeLanguage += HandleOnChangeLanguage;
}
void HandleOnChangeLanguage (LanguageManager thisLanguageManager)
{
m_text = LanguageManager.Instance.GetTextValue(m_langMgrKey);
}
~GuiLabel()
{
if (null != LanguageManager.Instance)
{
LanguageManager.Instance.OnChangeLanguage -= HandleOnChangeLanguage;
}
}
public override void Draw ()
{
GUI.Label(m_rect, m_text, m_style);
base.Draw ();
}
}
LanguageManager
is a long-living singleton object which is created at the first use of LanguageManager.Instance
. GuiElementBase
doesn't do much, it contains a Rect m_rect
which represents the position of the label. It is NOT derived from MonoBehavior, it's just an ordinary class.
Here are my questions:
1) When to unsubscribe from OnChangeLanguage?
I don't know how I should handle unsubscribing from the LanguageManager's OnChangeLanguage
event. I suppose, doing it in the destructor is OK if the GuiLabel gets destroyed BEFORE the LanguageManager?
However, what if the GuiLabel and the LanguageManager are destroyed at the same time which could happen if a GuiLabel is still being displayed/used and the user choses to quit the app. When should I unsubscribe from the event in this case?
Does it even make sense to access the LanguageManager.Instance in GuiLabel's destructor? Or could this do something terrible?
2) How to unsubscribe on the main thread?
The second question is more Unity-specific. The above code produces the following error message when the application is quit:
CompareBaseObjectsInternal can only be called from the main thread. Constructors and field initializers will be executed from the loading thread when loading a scene. Don't use this function in the constructor or field initializers, instead move initialization code to the Awake or Start function.
I understand it that Unity wants me do something on the main thread instead of another tread. The problematic line is null != LanguageManager.Instance
in the destructor. Do I have to compare this instance on the main thread? How would I do that?