Why are both my if and else statements true?

Logic says, if the first one is true, it executes the code and doesn’t move on to the else statement. That’s not true in my case.

I have this code:

public void CheckPuzzle()
    {
        for(int i = 1; i <= 3; i++)
        {
            currentPuzzlePiece = PlayerPrefs.GetInt("puzzle piece number");
            nextPuzzlePiece = i + 1;
            if(currentPuzzlePiece == nextPuzzlePiece - 1)
            {
                // Correct
                Debug.Log("Second IF: Correct");
            } else
            {
                    // Incorrect
                    Debug.Log("Second IF: Incorrect");
            }
        }
    }

Which is triggered on a collider:

private void OnTriggerEnter(Collider other)
    {
        PlayerPrefs.SetInt("puzzle piece number", puzzlePieceNumber);
        firstPuzzle.CheckPuzzle();
    }

And I am getting both in console:
9450182--1326584--upload_2023-11-4_12-34-17.png

I’m also not sure if my game logic is right.
I’m trying to make it so you have to step on these in the correct order, if you fail, it resets the player to try again:

How I’m “attempting” to do it now, is when you step on one, it saves what you stepped on with PlayerPrefs and compares that to the correct square. If it’s wrong, you have to try again. If it’s right, you have to guess the next square.

Note: each block has a Puzzle Piece Number assigned in the inspector. Blue is 1, Green is 2, Red is 3.

Help is greatly appreciated. Thank You.

UPDATE:

Puzzle Game Object (containing the FirstPuzzle.cs component) is on each block. Because:

I always have to do this:

[SerializeField] GameObject firstPuzzleGameObject;
private FirstPuzzle firstPuzzle;

private void Start() {
firstPuzzle = firstPuzzleGameObject.GetComponent<FirstPuzzle>();
}

Because if I do it like everyone else:

private FirstPuzzle firstPuzzle;

private void Start()
    {
        firstPuzzle = GetComponent<FirstPuzzle>();
    }

I get a null object reference and can’t find the solution online.

  • Just using Debug.Log(“…”) with a constant string is Bronze Medal debugging.

  • Using Debug.Log($“… {variable} …”) with additional information to help you understand what’s happening is Silver Medal debugging. When in doubt, show what’s happening with specific variables at the points you’re using them.

The kind of log you put in your loop would be a lot more informative if you showed the progress of the loop.
Debug.Log($"In loop iteration {i}, second IF: Correct"); It would help you see that the condition was true for one loop cycle, and false for a different loop cycle (a different value of i).

In your second case, again, more debugging information is important. The null object reference isn’t happening in your firstPuzzle = GetComponent<FirstPuzzle>(); statement, because you’re not using any object references that could possibly be null. At the point you get the null object reference error, you want to add more Debug.Log() calls to show you where you are, and ideally WHAT values you’re working with.

  • [Using a single-stepping code debugger with breakpoints and watchpoints is Gold Medal, but that’s outside the scope of this feedback.]
1 Like

You will NEVER find the solution to NullReferenceException online.

The solution is in your project and in front of you and requires YOU to find it.

The answer is always the same… ALWAYS!

How to fix a NullReferenceException error

https://forum.unity.com/threads/how-to-fix-a-nullreferenceexception-error.1230297/

Three steps to success:

  • Identify what is null ← any other action taken before this step is WASTED TIME
  • Identify why it is null
  • Fix that

All that said, do you NEED to be doing this crazy GetComponent() stuff? If not, stop it. Here’s why:

Keep in mind that using GetComponent() and its kin (in Children, in Parent, plural, etc) to try and tease out Components at runtime is definitely deep into super-duper-uber-crazy-Ninja advanced stuff.

Here’s the bare minimum of stuff you absolutely MUST keep track of if you insist on using these crazy Ninja methods:

  • what you’re looking for:
    → one particular thing?
    → many things?
  • where it might be located (what GameObject?)
  • where the Get/Find command will look:
    → on one GameObject? Which one? Do you have a reference to it?
    → on every GameObject?
    → on a subset of GameObjects?
  • what criteria must be met for something to be found (enabled, named, etc.)

If you are missing knowledge about even ONE of the things above, your call is likely to FAIL.

This sort of coding is to be avoided at all costs unless you know exactly what you are doing.

Botched attempts at using Get- and Find- are responsible for more crashes than useful code, IMNSHO.

If you run into an issue with any of these calls, start with the documentation to understand why.

There is a clear set of extremely-well-defined conditions required for each of these calls to work, as well as definitions of what will and will not be returned.

In the case of collections of Components, the order will NEVER be guaranteed, even if you happen to notice it is always in a particular order on your machine.

It is ALWAYS better to go The Unity Way™ and make dedicated public fields and drag in the references you want.

I highly recommend learning how to debug code. Your productivity will skyrocket, as you will be able to troubleshoot any issues that arise in your code without having to ask in the Unity forums.

Here are a few YouTube videos that I’ve found:

https://www.youtube.com/watch?v=rjNDXKgbhgY

https://www.youtube.com/watch?v=wt2YdrUlzgg

2 Likes

I appreciate the response.

The purpose of the Debug.Log is to see which one was firing. So, all I needed for that was a string. I was trying to figure out the game logic. But, I will change the Debug.Log to provide more information. Thank You.

@Kurt-Dekker anytime I get a null reference error, the first thing I check ALWAYS is what’s null. In this case, I just don’t get it because I do it like everyone else.

I know that the script exists, so why would it say the reference to the script is null? Not sure I understand the logic in that. I think I just realized I should be using FindObjectOfType<>();

Sometimes I forget about the different options I have. I wish I had the documentation memorized.

I do refer to the documentation when I don’t understand something; however, there’s times when I’m trying to use the wrong way and reading the documentation will only tell you about what you’re looking up, not other ways of accomplishing it… or the right way to accomplish something.

I do know various ways of debugging code. The reason I did it like this is because the ONLY thing I was checking for (at the time) was which if statement was firing so I knew if my game logic was right.

I was checking, if I stepped on the right sequence of blocks, did “correct” display? I took the easy way out. I don’t think logging errors to console would give me the info I was checking for.

Respectfully, you needed more than a string because you got BOTH answers, and you didn’t know why. Hence the additional info, to show you why.

Here are three people. George, Betty, Winston.

If it’s Winston, say yes, else say no.
“No.”
If it’s Winston, say yes, else say no.
“No.”
If it’s Winston, say yes, else say no.
“Yes.”

1 Like

Right, so in your example case the log messages would be $"No, it's acually {variable}". In this case it would be clear what the actual value is and then you’re off on your way to figure out why.

Just to make that clear: You check your if statement 3 times since it’s in a loop. One of the values (the one you get from the player prefs) would most likely be the same in each iteration (unless you have actually code inside that loop that changes it). When one of the value is constant during the for loop and the other changes, of course only during one iteration could the condition be true and false in any other.

As you can even see in your screenshot, you have enabled “collapse” in the console which can be misleading. You didn’t got one true and one false, you got two false and one true just as expected with 3 iterations.

Your “if” is inside a for loop, so it executes 3 times.

As Bunny83 said, the console is printing “Second IF: Correct” one time and “Second IF: Incorrect” 2 times (see the little numbers to the right of each console message, when the console is collapsed these tell you how many times each message has been printed). So out of the 3 times the if is evaluated, 2 of them evaluate to false and the “else” clause gets executed instead.

In practice, all your code does is compare “currentPuzzlePiece” with 1, 2 and 3 then print “Correct” the one time it matches and “Incorrect” the 2 times it doesn’t.

1 Like