Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Problem with game objects active at wrong times

Discussion in 'Scripting' started by Starmind01, Aug 29, 2021.

  1. Starmind01

    Starmind01

    Joined:
    May 23, 2019
    Posts:
    78
    I am working on a vr game that has a arcade style game inside of it. Everything works, but I have two gameobjects that will appear during the gameplay that should not. I did stay up pretty late last night and like most Germans, I am pretty sure I over thought my script. A lot of bad habits in my script.

    My question is, how do I fix my script? I think it has something to do with the coroutine for the start screen, in which I have added bools to stop. It works but at random. If you notice in the video below, both the game over screen and the game start screen overlap and are on during gameplay.

    So the bases of the game is simple flappy bird clone, but I have added one more screen to make it look like an arcade game. Also it needs credits to play. If you have credits to play then you can play.

    Now thinking about it, I also want to add one more screen with demo gameplay and possible highscore screen. But need to fix this before going on with it. Just need better eyes to see where I failed.

    Thank you!

    Code (CSharp):
    1.  public GameObject gameOver;
    2.     public GameObject startGame;
    3.     public GameObject player;
    4.     public Transform SpawnPoint;
    5.     public GameObject ShipSpawn;
    6.     public float timeToWait;
    7.     SpawnShips spawn;
    8.     AstroFlappyScore afs;
    9.     public GameObject[] ships;
    10.     Rigidbody2D rb;
    11.     public AudioSource backgroundAudio;
    12.     public AudioClip clipGameOver;
    13.     public AudioClip clipIdleGame;
    14.     public AudioClip clipPlayGame;
    15.     public bool startScreen;
    16.     public float screenWait;
    17.     public static int credit = 0;
    18.     private int creditUsed = 1;
    19.     public TMP_Text creditText;
    20.     public bool hasCredit;
    21.     public bool atPlay;
    22.  
    23.     private void Awake()
    24.     {
    25.         startScreen = true;
    26.         atPlay = false;
    27.         startGame.SetActive(true);
    28.         gameOver.SetActive(false);
    29.         backgroundAudio.clip = clipIdleGame;
    30.         backgroundAudio.Play();
    31.         backgroundAudio.loop = true;
    32.     }
    33.     public void PlayGame()
    34.     {
    35.         if(hasCredit)
    36.         {
    37.             atPlay = true;
    38.             credit -= creditUsed;
    39.             startGame.SetActive(false);
    40.             startScreen = false;
    41.             player.SetActive(true);
    42.             gameOver.SetActive(false);
    43.             player.transform.position = SpawnPoint.transform.position;
    44.             rb = player.GetComponent<Rigidbody2D>();
    45.             rb.isKinematic = true;
    46.             if(atPlay && !startScreen)
    47.             {
    48.                 StartCoroutine(GameStart());
    49.             }
    50.         }
    51.     }
    52.     public void GameOver()
    53.     {
    54.         atPlay = false;
    55.         startScreen = false;
    56.         startGame.SetActive(false);
    57.         if (backgroundAudio.isPlaying)
    58.         {
    59.             backgroundAudio.loop = false;
    60.             backgroundAudio.Stop();
    61.             backgroundAudio.clip = clipGameOver;
    62.             backgroundAudio.Play();
    63.         }
    64.         AstroFlappyScore.score = 0;
    65.         gameOver.SetActive(true);
    66.         ShipSpawn.SetActive(false);
    67.         player.SetActive(false);
    68.         ships = GameObject.FindGameObjectsWithTag("clone");
    69.         foreach(GameObject ship in ships)
    70.         {
    71.             Destroy(ship);
    72.         }
    73.         StartCoroutine(IdleScreen());
    74.     }
    75.     IEnumerator GameStart()
    76.     {
    77.         startScreen = false;
    78.         atPlay = true;
    79.        if(!startScreen)
    80.         {
    81.             startGame.SetActive(false);
    82.             yield return new WaitForSeconds(timeToWait);
    83.             backgroundAudio.clip = clipPlayGame;
    84.             backgroundAudio.Play();
    85.             backgroundAudio.loop = true;
    86.             rb = player.GetComponent<Rigidbody2D>();
    87.             rb.isKinematic = false;
    88.             ShipSpawn.SetActive(true);
    89.             if (spawn != null)
    90.             {
    91.                 spawn.Replay();
    92.             }
    93.             if (afs != null)
    94.             {
    95.                 afs.ResetScore();
    96.             }
    97.         }
    98.     }
    99.  
    100.     IEnumerator IdleScreen()
    101.     {
    102.         if (!startScreen && !atPlay)
    103.         {
    104.             startScreen = true;
    105.             atPlay = false;
    106.             yield return new WaitForSeconds(screenWait);
    107.             startGame.SetActive(true);
    108.             gameOver.SetActive(false);
    109.             backgroundAudio.clip = clipIdleGame;
    110.             backgroundAudio.Play();
    111.             backgroundAudio.loop = true;
    112.         }
    113.     }
    114.  
    115.     private void Update()
    116.     {
    117.         creditText.text = "Credits:" + credit.ToString();
    118.         if(!hasCredit)
    119.         {
    120.             if(!atPlay && startScreen)
    121.             {
    122.                 StartCoroutine(IdleScreen());
    123.             }
    124.         }
    125.         if(credit >= 1)
    126.         {
    127.             hasCredit = true;
    128.         }
    129.         if(credit == 0)
    130.         {
    131.             hasCredit = false;
    132.         }
    133.     }
    134. }
    135.  
     
  2. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    38,520
    Okay, that was hilarious. Thanks for the giggle!! I love German engineering and precision mindset. The world needs more of it.

    Looking at your script, the first thing that jumps out at me is that you are doing things in Awake() that have to do with other GameObjects. Generally that is to be avoided. The reason is that those objects may or may not have already had their Awake() calls, so the outcome may be unpredictable.

    Generally Awake() should be used only for things on the same GameObject (ideally only for things in this script).

    If you want to tinker with other things, it is best to do so in Start().

    As a fellow engineer let me observe this is a wise strategy!

    ALSO... if changing to doing things in Start() does not have any impact (and it might not!), then one way to track down what is happening is the time-honored Debug.Log() technique, and here is my standard blurb for that.

    What is often happening in these cases is one of the following:

    - the code you think is executing is not actually executing at all
    - the code is executing far EARLIER or LATER than you think
    - the code is executing far LESS OFTEN than you think
    - the code is executing far MORE OFTEN than you think
    - the code is executing on another GameObject than you think it is

    To help gain more insight into your problem, I recommend liberally sprinkling Debug.Log() statements through your code to display information in realtime.

    Doing this should help you answer these types of questions:

    - is this code even running? which parts are running? how often does it run? what order does it run in?
    - what are the values of the variables involved? Are they initialized? Are the values reasonable?
    - are you meeting ALL the requirements to receive callbacks such as triggers / colliders (review the documentation)

    Knowing this information will help you reason about the behavior you are seeing.

    You can also put in Debug.Break() to pause the Editor when certain interesting pieces of code run, and then study the scene

    You could also just display various important quantities in UI Text elements to watch them change as you play the game.

    If you are running a mobile device you can also view the console output. Google for how on your particular mobile target.

    Here's an example of putting in a laser-focused Debug.Log() and how that can save you a TON of time wallowing around speculating what might be going wrong:

    https://forum.unity.com/threads/coroutine-missing-hint-and-error.1103197/#post-7100494

    ALSO: you might enjoy this interesting graphic:

    https://docs.unity3d.com/Manual/ExecutionOrder.html
     
  3. Starmind01

    Starmind01

    Joined:
    May 23, 2019
    Posts:
    78

    Thank you for your reply! I went in and I was able to define and move things around to get it to work better, but not at all perfect. I will keep chipping at it and see where it leads. Might have to start from scratch or leave it and come back to it later with new eyes.
     
  4. Starmind01

    Starmind01

    Joined:
    May 23, 2019
    Posts:
    78
    Okay so after a few Debug.Breaks, I was able to see that I had some bools in the wrong order and that I forgot to remove code that was no longer being used. Also noticed that while the code worked, I still kept having issues. The issues was with the button being used. It would double and sometimes even triple press causing the coroutines to restart. To fix that I simply removed that button and enabled a decoy.

    So while playing, the real button is not active until the start screen. Sorta like when you would add a coin and have to wait for the game to do its thing before you could play.

    Thank you for the help! Now off to make more games to fill up the arcade!
     
    Kurt-Dekker likes this.