2

General Info
Working on a simple 2D Gui for a game mod to enable / disable mod functions through buttons.

The problem
When a user clicks a button, the text changes from "function: off" to "function: on" and visa versa. It uses a simple boolean to accomplish this. To make it more clear to the user which functions have been enabled / disabled, I'm trying to change the text color just as well.

What I've tried myself to accomplish this
Doing a bit of research myself, it became clear to me that the color of text on a button can be changed as follows:

private static GUIStyle enabledText;
private static GUIStyle disabledText;

public static void Start()
{
    enabledText = new GUIStyle(GUI.skin.button);
    enabledText.normal.textColor = Color.green;

    disabledText = new GUIStyle(GUI.skin.button);
    disabledText.normal.textColor = Color.red;
}

Then wherever needed:

GUILayout.Button("Label", style);

Here is an example of how I implement a button:

if (GUILayout.Button("God Mode: " + (s_isGodMode ? "On" : "Off")))
{
    s_isGodMode = !s_isGodMode;
}

So putting that and the research done earlier together, this would be the result:

if (GUILayout.Button("God Mode: " + (s_isGodMode ? "On" : "Off"), (s_isGodMode ? enabledText : disabledText)))
{
    s_isGodMode = !s_isGodMode;
}

Which compiles fine and without any errors or warnings. However, when trying to load it in, I'm presented with:

[Error : Unity Log] NullReferenceException: Object reference not set to an instance of an object
Stack trace:
UnityEngine.GUILayoutUtility.DoGetRect (UnityEngine.GUIContent content, UnityEngine.GUIStyle style, UnityEngine.GUILayoutOption[] options) (at :0)
UnityEngine.GUILayoutUtility.GetRect (UnityEngine.GUIContent content, UnityEngine.GUIStyle style, UnityEngine.GUILayoutOption[] options) (at :0)
UnityEngine.GUILayout.DoButton (UnityEngine.GUIContent content, UnityEngine.GUIStyle style, UnityEngine.GUILayoutOption[] options) (at :0)
UnityEngine.GUILayout.Button (System.String text, UnityEngine.GUIStyle style, UnityEngine.GUILayoutOption[] options) (at :0)
QualityOfLife.QOL.Core.Cheats.DisplayGUI () (at <98e4be18d16b445790f620c81671da54>:0)
QualityOfLife.QOL.EntryPoint.ValheimToolerWindow (System.Int32 windowID) (at <98e4be18d16b445790f620c81671da54>:0)
UnityEngine.GUILayout+LayoutedWindow.DoWindow (System.Int32 windowID) (at :0)
UnityEngine.GUI.CallWindowDelegate (UnityEngine.GUI+WindowFunction func, System.Int32 id, System.Int32 instanceID, UnityEngine.GUISkin _skin, System.Int32 forceRect, System.Single width, System.Single height, UnityEngine.GUIStyle style) (at :0)

The resulting menu is just a blank rectangle. Removing the second parameter to change the GUI button text color resolves the problem and makes it work perfectly fine again. What exactly am I doing wrong and how should I resolve the issue?

icecub
  • 8,615
  • 6
  • 41
  • 70
  • Does this answer your question? [What is a NullReferenceException, and how do I fix it?](https://stackoverflow.com/questions/4660142/what-is-a-nullreferenceexception-and-how-do-i-fix-it) – Max Play Jan 10 '23 at 19:04
  • @MaxPlay I know what a null reference exception is. I understand that something is being called that doesn't exist or is "null". The issue is that I followed the docs as expected, yet being represented with it. Hence I wonder if I misunderstood something or made a mistake. – icecub Jan 10 '23 at 19:07

1 Answers1

2

You have:

public static void Start()

why is that static? Is your class a MonoBehaviour? Should not be static, for Unity to find/call this function (I think*). Just in case that never gets called, your enabledText and disabledText variables will not be initialized, and that will cause the null reference exception.

* you can make Start() async or make it return IEnumerator, but I don't think static works, because it should be called per object, not globally. https://docs.unity3d.com/ScriptReference/MonoBehaviour.Start.html

KYL3R
  • 3,877
  • 1
  • 12
  • 26
  • No it's not MonoBehaviour. It doesn't rely on the game to call it. The main script manually calls it to initiate the GUI menu. There's different variables in it as well for labels, who work perfectly fine. Side note: It's static because it's a single menu. No reason to instantiate something that's only used once. Changes made to the menu should effect it everywhere obviously. – icecub Jan 10 '23 at 19:01
  • Well I figured, because it's called "Start" and you work with Unity. So did you really call `Start` before using `enabledText` in a GUIButton? Maybe Debug.Log these two variables to see if they are null. – KYL3R Jan 10 '23 at 19:07
  • Hmm it seems you are right. It's being called, but only later on. Not before. Thanks for pointing it out to me! – icecub Jan 10 '23 at 19:10
  • 1
    Yup, that was exactly it. Moved it to a different location and it instantly worked fine! Much appreciated! – icecub Jan 10 '23 at 19:14