- Home /
Why isn't a function being called by my boolean?
Hey Unity! I have this script that I made and it basically turns a canvas on and off when a certain button is pressed by checking if a boolean is true or false (if it's true the canvas should be turned on, false it should be turned off), but I've been having some issues with it. It seems like a really basic script and I don't know why it's not working. Sometimes it will throw me a NullReference error, other times it will just not work. The script works by making a boolean true if Space is pressed (and the boolean is false) and making the boolean false if Space is pressed (and the boolean is true). In the inspector I can see the bool (I made it public) being turned on and off, but the canvas is not rendering in the function that should be called when the boolean is made true / false. Any help would be appreciated. I hate asking for help because I don't like being spoonfed but I've been going at this since Tuesday.
using UnityEngine;
using UnityEngine.UI;
public class Inventory : MonoBehaviour
{
public Canvas canvas;
public bool openInventory; // The inventory is disabled in the inspector
void Update()
{
if (Input.GetKeyDown(KeyCode.Space))
{
openInventory = !openInventory;
}
if (openInventory == true)
{
canvas.enabled = true;
// I want to check to see if the player pressed Space again while the inventory is open
// If they did then i want it to close
if (Input.GetKeyDown(KeyCode.Space))
{
canvas.enabled = false;
}
// I need the system to know if the inventory is being opened or closed because I want it to play different audios
}
}
}
Answer by Eno-Khaon · Oct 09, 2021 at 07:19 PM
You've gotten yourself trapped in your order of operations.
The first thing you're overlooking is that Input.GetKeyDown() lasts for the entire frame that it's true. As a result, you're checking it before changing the value of "openInventory" then checking it again immediately after, resulting in "canvas" changing to true, then back to false, all within the same frame.
To get past this, let's change things up a bit by making use of a Property instead. This way, you can combine various elements of this into a single action (and look at it from a different angle at the same time):
bool bOpenInventory;
// You read "openInventory" wherever it's needed,
// but the "real" value is "bOpenInventory", hidden
// from view from other scripts as needed
public bool openInventory
{
get
{
return bOpenInventory;
}
set
{
bOpenInventory = value;
canvas.enabled = value;
// As desired, audio can be played from here
// as well, among other places. For example:
AudioClip inventoryAudio = value ? openInvSound : closeInvSound;
// [play audioclip]
}
}
void Update()
{
if(Input.GetKeyDown(KeyCode.Space))
{
// Now, this will set the value of the boolean
// as well as turning the canvas on/off
openInventory = !openInventory;
}
}
Answer by justinenayat · Oct 09, 2021 at 07:05 PM
Try something like this:
public class Inventory : MonoBehaviour
{
public Canvas canvas;
public bool openInventory; // The inventory is disabled in the inspector
void Update()
{
if (Input.GetKeyDown(KeyCode.Space))
{
if (openInventory == true)
//play sound1
else
//play sound2
openInventory = !openInventory;
}
if (openInventory == true)
canvas.enabled = true;
else
canvas.enabled = false;
}
Answer by jmhoubre · Oct 09, 2021 at 07:27 PM
Hello,
the error stems from the fact that GetKeyDown is set to true or false for the whole frame. If inventory is closed and space is activated, line 13 sets openInventory to true. We therefore enter the block of line 16. The canvas is therefore activated. Line 21, GetKeyDown is always true (same frame), so we disable the canvas. The following code is not fundamentally different from that of justinenayat:
using UnityEngine;
using UnityEngine.UI;
public class Inventory : MonoBehaviour
{
public Canvas canvas;
public bool openInventory;
void Update ()
{
if (Input.GetKeyDown (KeyCode.Space))
{
openInventory = !openInventory;
if (openInventory == true)
{
canvas.enabled = true;
// Play one sound.
}
else
{
canvas.enabled = false;
// Play another sound.
}
}
}
}