Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Help during Game Jam please: Static Bools & a "centralized" Canvas display

Discussion in 'Scripting' started by misterG420, Apr 18, 2020.

  1. misterG420

    misterG420

    Joined:
    Jan 23, 2020
    Posts:
    31
    Dear unity nerds, I am really stuck and appreciate any SIMPLE help on the following code challenge:

    I have a 2D click adventure, where you click with your mouse on different colliders, such as a door to go to the next level. There are also items that - if you click them - get added to your Canvas (enabled). In the specific case, those two items are "Bone" and "Key". In level 1 you can collect a key, that gets shown in your UI. As you go into level 2, you collect a key. If you now go back to level 1, you naturally don't have that key anymore, because at the moment the "key" is bound to a bool, that sits on a game manager and every level has a game manager script where the bool is only correct for that level.

    I figured that I need so somehow set the two bools for "key" and "bone" to static and somehow break out the Bools and the associated Canvas, so that each Level I can access the correct status of the two bools and display the Canvas accordingly.

    Few hours of research and tutorials later, I have grasped some key words, but nothing else. E:g. there are talks about static bools and using singletons and get and set but I am really a novice and unless I see the actual implementation in my script, I can't yet make the transfer to my own script. The code is a mess, but I pray that someone can help me out with the script! I would be for ever thankful! Honestly!

    PS: I know I could delete the counting of the amount of "key" and "bone" as there will always only be one item of each, but it is a relict that I havn't deleted yet.

    As you might see from the script, the script manages everything (detecting the click, activating the Canvas, etc.). You can ignore any code after line 60, as it only refers to the Scenemanager which poses no issues.

    Code (CSharp):
    1. using UnityEngine;
    2. using UnityEngine.SceneManagement;
    3.  
    4. public class AdventureScript : MonoBehaviour
    5. {
    6.  
    7.     public Vector3 mousePos;
    8.     public Camera mainCamera;
    9.     public Vector3 mousePosWorld;
    10.     public Vector2 mousePosWorld2D;
    11.  
    12.     RaycastHit2D hit;
    13.  
    14.     public Vector2 targetPos;
    15.  
    16.     public bool boneCollectedBool; //for the frist level, where you need the goat bone to smash open the hole in the wall;
    17.     public int collectedBone; //for the frist level, where you need the goat bone to smash open the hole in the wall;
    18.  
    19.     public bool keyCollectedBool; //for the key stuck in the toilet to open the hatch;
    20.     public int collectedKey; //for the key stuck in the toilet to open the hatch;
    21.  
    22.     public GameObject keyUIElement1; //This is the bone of the first room, to smash open the hole in the wall;
    23.     public GameObject keyUIElement2; //This is for the hatch key stuck in the toilet;
    24.  
    25.  
    26.  
    27.     void Update()
    28.     {
    29.  
    30.         if (Input.GetMouseButtonDown(0))
    31.         {          
    32.             mousePos = Input.mousePosition;
    33.             mousePosWorld = mainCamera.ScreenToWorldPoint(mousePos);
    34.             mousePosWorld2D = new Vector2(mousePosWorld.x, mousePosWorld.y);
    35.  
    36.             hit = Physics2D.Raycast(mousePosWorld2D, Vector2.zero);
    37.  
    38.             // check if hiting a collider
    39.             if (hit.collider != null)
    40.             {
    41.                 Debug.Log("Hit an object with a collider!: " + hit.collider.gameObject.tag);
    42.    
    43.                 if (hit.collider.gameObject.tag == "Bone")
    44.                 {
    45.                     // if hitting the collider with tag "key" then  set Bool to true;
    46.                      boneCollectedBool = true;
    47.  
    48.                     // Simultaneaously, add collectedKey in the CanvasHUD;
    49.                     collectedBone += collectedBone;
    50.                     keyUIElement1.SetActive(true);
    51.  
    52.                 }
    53.  
    54.                 if (hit.collider.gameObject.tag == "ToiletWithHatchKey")
    55.                 {
    56.                     // if hitting the collider with tag "key" then set Bool to true;
    57.                      keyCollectedBool = true;
    58.  
    59.                     // Simultaneaously, add collectedKey in the CanvasHUD;
    60.                     collectedKey += collectedKey;
    61.                     keyUIElement2.SetActive(true);
    62.                     Debug.Log("Hooray, Key retrieved from toilet!");
    63.  
    64.                 }
    65.  
    66.                 else if (hit.collider.gameObject.tag == "Hole")
    67.                 {
    68.                     Debug.Log("You clicked on the Hole!");
    69.                     if (boneCollectedBool == true)
    70.                     {
    71.              
    72.                     SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex + 1);
    73.                     Debug.Log("You HAVE the bone and can smash the hole in the wall!");
    74.                     }
    75.                     else
    76.                     {
    77.                         print("You don't have any solid object to smash open this hole");
    78.                     }
    79.  
    80.                 }
    81.  
    82.                 if (hit.collider.gameObject.tag == "OpenWallToCrawl")
    83.                 {
    84.                  
    85.                     SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex + 1); //should load the door_hallway now;
    86.                 }
    87.  
    88.                 if (hit.collider.gameObject.tag == "OpenWallToCrawlBACKtoLvl2")
    89.                 {
    90.                    
    91.                     SceneManager.LoadScene(2);
    92.                 }
    93.              
    94.                 if (hit.collider.gameObject.tag == "LadderUpstairs")
    95.                 {
    96.                    
    97.                     SceneManager.LoadScene(4);
    98.                 }
    99.  
    100.                 if (hit.collider.gameObject.tag == "LadderDownstairs")
    101.                 {
    102.                    
    103.                     SceneManager.LoadScene(3);
    104.                 }
    105.  
    106.                 if (hit.collider.gameObject.tag == "DoorToToilet")
    107.                 {
    108.  
    109.                     SceneManager.LoadScene(5); //should load the level 5 (toilet room)
    110.                 }
    111.  
    112.             }
    113.             else
    114.             {
    115.                 print("You did not click on anyting with a collider");
    116.             }
    117.         }
    118.     }
    119.  
    120.    
    121.  
    122. }
     
  2. ArachnidAnimal

    ArachnidAnimal

    Joined:
    Mar 3, 2015
    Posts:
    1,727
    You say "every level has a game manager script". That is an oxymoron when dealing with an inventory. A game manager (i.e. inventory) usually exists only once and persist throughout the life of a game session, not be re-created for every level. They way you have it you are resetting the inventory-related information every time you load a level. You could solve it by creating the static data, but usually static data will just lead to issues down the road.
    You might want to think about creating an Inventory manager, and using DontDestroyOnLoad to ensure the InventoryManager is carried from scene to scene.
    https://docs.unity3d.com/ScriptReference/Object.DontDestroyOnLoad.html
    Code (csharp):
    1.  
    2. public class Inventory : MonoBehaviour
    3. {
    4.     public static Inventory instance;
    5.  
    6.     public bool collectedKey;
    7.     public bool collectedBone;
    8.  
    9.     void Awake() {
    10.         instance = this;
    11.         GameObject.DontDestroyOnLoad(this.gameObject); //Keep this Inventory script when loading a new scene
    12.      }
    13. }
    14.  
    Code (csharp):
    1.  
    2. public class AdventureScript : MonoBehaviour
    3. {
    4.      //....
    5.     void BoneCollected()
    6.     {
    7.         Inventory.instance.collectedBone = true; //Player collected a bone
    8.      }
    9. }
    10.  
     
  3. misterG420

    misterG420

    Joined:
    Jan 23, 2020
    Posts:
    31
    Thank you so much! I always thought it would be nightmare to set something like this up! I can confirm, that the inventory manager now correctly displays the status of carrying items in every level.

    However, I applied the same method and code for a new UIManager, that should work the same way, no?


    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. public class UIManager : MonoBehaviour
    6. {
    7.     public static UIManager instance;
    8.  
    9.     public GameObject keyUIElement1; //This is the bone of the first room, to smash open the hole in the wall;
    10.     public GameObject keyUIElement2; //This is for the hatch key stuck in the toilet;
    11.  
    12.     void Awake()
    13.     {
    14.         instance = this;
    15.         GameObject.DontDestroyOnLoad(this.gameObject); //Keep this script when loading a new scene
    16.  
    17.     }
    18. }
    19.  
    Code (CSharp):
    1.       if (hit.collider != null)
    2.             {
    3.                 Debug.Log("Hit an object with a collider!: " + hit.collider.gameObject.tag);
    4.  
    5.                 if (hit.collider.gameObject.tag == "Bone")
    6.                 {
    7.                     // if hitting the collider with tag "key" then set instance's Bool to true;
    8.                     Inventory.instance.collectedBone = true;
    9.                     UIManager.instance.keyUIElement1.SetActive(true);
    10.                
    11.  
    12.                 }
    13.  
    14.                 if (hit.collider.gameObject.tag == "ToiletWithHatchKey")
    15.                 {
    16.                     // if hitting the collider with tag "key" then set instance's Bool to true;
    17.  
    18.                     Inventory.instance.collectedKey = true;
    19.                     UIManager.instance.keyUIElement2.SetActive(true);
    20.  
    21.                 }
    BUT: It only displays correctly for level 1 and then does not properly show the bone/key icon in the other levels on the UI canvas. The inspector highlights "missing game object", because there is no UIManager in every scene, where the Canvas objects are linked. I.e. The UIManager I've mentioned above exists once in Level 1 and I dragged the game objects to be displayed (the 2 canvas icons) onto the UIManager with the respective UIManager script. In the other levels, naturally, it can't retrieve the images because they are not dragged in that UIManager in that level...Do I need to do a different way with the UI-"instances"? Sorry, and thanks again! Do I need to set up the actual Canvas itself differently?

    PS: The Canvas is set up like this: UICanvas->CollectedItem1disabled->CollectedItem1enabled. Where the colelctedItem1disabled is ACTIVE (grey) and the child collectedItem1enabled is INACTIVE (white). With the UIManager I grab the inactive one and set it active. That's the plan :)
     
    Last edited: Apr 19, 2020
  4. misterG420

    misterG420

    Joined:
    Jan 23, 2020
    Posts:
    31
    Hooray! I am just an idiot! It all works now. I forgot that I also have to set active the canvas element outside the if-statement, e.g. in every scene, even if I don't click on an item with the tag "bone" or "key". It was that easy :)

    I did hower toss the idea of a separate UIManager and instead added the canvas elements in the adventureScript.

    Thanks all! The game jam may continue without mental breakdowns!
     
    Last edited: Apr 19, 2020