a method works and sometimes doesn't

Hi

i am making game for collecting some letters , if the player collect all letters , he will win and wil Victory level

i used this code but it works and sometimes doesn’t work

using UnityEngine;
using System.Collections;

public class Victory : MonoBehaviour {


   
    // Update is called once per frame
    void Update () {
    if (LetterA.GameInstance.shownA&&LetterC.GameInstance.shownC&&LetterR.GameInstance.shownR)
        Application.LoadLevel ("Victory");
    }
}

i think the problem might be in the void update, but i dont know what i should use instead
what do you suggest guys ?

thanks

Note: my idea in the game that the player should collect all letters to be able to win

^^^^

The void Update part means, the check needs to be performed in every frame. Your problem has nothing to do with that. However, it is not clear what could cause an issue other than that the flags are not properly set about which letters were collected.

the problem in my code i think is the combination, while calling the methods together , i have to use something instead of

if (LetterA.GameInstance.shownA&&LetterC.GameInstance.shownC&&LetterR.GameInstance.shownR)

shownA shownC shownR , are booleans stated on false , when the player collect those letter , they become true

what do you suggest me to use instead of that if ?

I think your problem is in another castle.

Might I ask you how do you set your variables GameInstance.shownA, etc?

If it sometimes works and sometimes doesn’t, clearly you have to revisit your other code. I would presume somewhere in collision where you set true when you pick up your unfortunate letters?

@Fajlworks

when i try LetterA.GameInstance.shownA) alone , it works , but when i put for example (LetterA.GameInstance.shownA && LetterC.GameInstance.shownC ) it doesn’t work directly, i have to try to collect letter a and letter c random times until it work, it just randomly works

here is the code of LetterA

using UnityEngine;
using System.Collections;

public class LetterA : MonoBehaviour {
   
    public bool shownA=false;
    public static LetterA GameInstance ;
    private LetterA()
    {
        GameInstance = this;
    }

    void OnTriggerEnter2D(Collider2D collisionObject) {       
        if (string.Equals (collisionObject.tag, "Bucket")) {

            Destroy (collider,0.5f);           

            Letter_A.Instance.ShowA();
            GameInstance.shownA=true;
            
        }

    }
}

and here is the code of the prefab of letter A

using UnityEngine;
using System.Collections;

public class Letter_A : MonoBehaviour {
    public GameObject A;
    public static Letter_A Instance;
    private Letter_A()
    {
        Instance = this;
    }

   

    public void ShowA(){

            A.SetActive (true);
            Debug.Log ("Enabled");
    }


}

the codes work fine , but the problem in the && , as long as i wanted to load the victory scene when the player collect the 3 letter C A R

Maybe put some debug code into your scripts checking if all values are true or what. Like Debug.Log (someBool); will tell you if someBool is true.

Ok, let’s take a different approach here. Instead trying to find what could possibly cause such an error, let us rewrite all of your classes, but this time properly.

Namely, the way you are using your classes. Both LetterA, LetterR, LetterC are using practically the same code. After all, they are letters. The way classes work is that they are meant to have multiple instances during the lifetime of the app. As soon as you create LetterA, you assign it to a global variable GameInstance.

Sure, it is convenient, but if you create a level with words C A R C H O A L, you have two instances of A and two of C, automatically overwriting your previous GameInstance with the second. Hence, the code breaks and you can’t reuse the same code for different letters.

Let’s create a simple class called PickableItem, which will have all the functionality required for this game to work. Sure, we are using Letters in this game, but giving it a generic name will allow us to use it in, perhaps, another game. After all, in Unity Component based scripting it is better to think what are GameObjects composed of, instead what an GameObject is.

public class PickableItem : MonoBehaviour
{
     public GameObject hiddenObject;
     public string requiredTag;
   
     bool m_pickedFlag = false;
     public bool IsPickedUp
     {
           set
           {
                 m_pickedFlag = value;
                 hiddenObject.SetActive(m_pickedFlag);
           }
           get
           {
                 return m_pickedFlag;
           }
     }

     void OnTriggerEnter2D(Collider2D collisionObject)
     {    
           if (IsPickedUp)
                 return;

           if (collisionObject.tag == requiredTag)
           {
                  IsPickedUp = true;
           }
     }
}

And a main game object script that will behave as a game manager.

using System.Collections.Generic;
public class GameManager : MonoBehaviour
{
     public List<PickableItem> items;
     public int nextLevel;

     void Update()
     {
          int result = 0;
          for (int i = 0; i < items.Count; i++)
          {
                 if (items[i].IsPickedUp)
                      result++;
          }

          if (result == items.Count)
                PrepareVictoryScene();
     }

     void PrepareVictoryScene()
     {
           Application.LoadLevel(nextLevel);
     }
}

Okay, let us review the code above. GameManager will behave as a singleton, hence just create one empty game object and assign it a GameManager script.

Now create your letter game objects. Now I’m kinda saying things blindly since you haven’t provided how you really set up your classes (you had LetterA and Letter_A classes with different functionality so I can’t help myself), but I would do the workflow like this:

Create all your letters on the scene and give them PickableItem script. Assign the required tag in the inspector. Add your hidden gameObjects as a child of the letter and set it as Deactivated. Also link it in the inspector don’t forget. I assume the hidden gameObject looks differently from the original letter, so the player can see it was picked up.

Once you created all of your letters, assign them to your GameManager items list in the inspector. That should be it! Once you start the program, GameManager will enumerate all your PickableItems and once they all have IsPickedUp set to true, you should proceed to the victory screen.

I hope this wall of text helps you a bit. Singletons are okay sometimes to use, GameManager could be a singleton, but then again it could create a bad habit of linking your singleton reference to many scripts, effectively making them more dependable on the GameManager. Then you couldn’t take your PickableItem script and put it in another project, you would have to refactor it. By keeping your PickableItem unaware of any game logic, they become more reusable and that is the point of Unity programming, creating small chunks of code that can be used on many different game object.

Also, I would recommend you to choose wisely class names. By creating LetterA and Letter_A, it will confuse your fellow programmers that work together on same project, because you cannot understand what the class does from the naming. Having a PickableItem, I’m sure every newcomer can immediately understand what this class is used for.

Good luck with your project, and sorry for the wall of text!

1 Like

Good response lol

When you can’t fix it, I say break it and rebuild :slight_smile:

2 Likes

Thanks for your effort and work :slight_smile: , but you took me too far away , and i dont know how to apply this for all letters and how to build my game as your code , i know the problem is in this line

        if (LetterA.GameInstanceA.shownA && LetterC.GameInstanceC.shownC && LetterR.GameInstanceR.shownR)
        
     
            Application.LoadLevel ("Victory");

}

when i only use one letter for example

  if (LetterA.GameInstanceA.shownA)
Application.LoadLevel ("Victory");

the game works fine and each time i collect A it works and load the level

That’s too bad. I would highly recommend you to reconsider a different approach, as using different classes for different letters just begs for bugs in the long run, since now you have to maintain 3 different classes with same code instead of working with just one simple class. Also, you have to consider your game will have all kinds of different words and different letters as you continue developing, I’m afraid you will have a lot of trouble later.

Also, my suggestion is really easy to implement. If you’re having trouble, I would highly recommend watching few Unity tutorials, even downloading those free Unity Example projects from Asset Store could be of a great help, just looking and examining all of the classes; how everything is build and how it all works. If you plan to develop games seriously, then please help yourself with them. Good luck!

As indicated the line of code you are pointing to is not the problem. The problem is where you set the bools.

Your code is broken and not extendable. So a full rewrite would be best. Do what @Fajlworks has suggested.

If you insist on using broken code you must fix the classes for letter C and letter R to match letter A. Don’t do this, it will not work in the long run.

@Fajlworks ok but would you please provide your code with comments explaining to me what does each line will do ? i think you alright because i’ll use multiple of letters later not only 3 or 4 letters so i think i need game manager as the one you make , put please write comments for the code to help me understand the steps of the code and understand your thoughts :slight_smile: :slight_smile: