Search Unity

How to make Game Replay work?

Discussion in 'Scripting' started by roopesh23, Sep 19, 2022.

  1. roopesh23

    roopesh23

    Joined:
    Jul 11, 2022
    Posts:
    10
    I am making Replay logic for my game, where when I click replay I got to the Main Page. The problem I am facing is that after clicking Play on the game after coming from Replay, the Zombie character in my game is not showing up. The game is running without the player. I am posting the script, check the Replay function which is attached to Replay button in the game.

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using UnityEngine.Assertions;
    5.  
    6. public class GameManager : MonoBehaviour
    7. {
    8.     public static GameManager instance = null;
    9.  
    10.     private bool playerActive = false;
    11.     private bool gameOver = false;
    12.     private bool gameStarted = false;
    13.     private GameObject newZombie;
    14.  
    15.     [SerializeField] private GameObject mainMenu; //contains main menu content
    16.     [SerializeField] private GameObject endGame; //contains game over content
    17.  
    18.     [SerializeField] private GameObject zombie;
    19.  
    20.     public bool PlayerActive{
    21.         get{
    22.             return playerActive;
    23.         }
    24.     }
    25.  
    26.     public bool GameOver{
    27.         get{
    28.             return gameOver;
    29.         }
    30.     }
    31.  
    32.     public bool GameStarted{
    33.         get{
    34.             return gameStarted;
    35.         }
    36.     }
    37.  
    38.     void Awake()
    39.     {
    40.         if(instance == null){
    41.             instance = this;
    42.         }else if(instance != this){
    43.             Destroy(gameObject);
    44.         }
    45.  
    46.         Assert.IsNotNull(mainMenu);
    47.         Assert.IsNotNull(endGame);
    48.  
    49.         DontDestroyOnLoad(gameObject);
    50.     }
    51.  
    52.     // Start is called before the first frame update
    53.     void Start()
    54.     {
    55.         endGame.SetActive(false);
    56.         mainMenu.SetActive(true);      
    57.     }
    58.  
    59.     // Update is called once per frame
    60.     void Update()
    61.     {
    62.        
    63.     }
    64.  
    65.     public void PlayerCollided()
    66.     {
    67.         gameOver = true;
    68.         endGame.SetActive(true);
    69.         mainMenu.SetActive(false);
    70.         DontDestroyOnLoad(gameObject);
    71.        
    72.  
    73.     }
    74.  
    75.     public void PlayerStartedGame()
    76.     {
    77.         playerActive = true;
    78.     }
    79.  
    80.     public void EnterGame()
    81.     {
    82.         endGame.SetActive(false);
    83.         mainMenu.SetActive(false);
    84.         gameStarted = true;
    85.     }
    86.  
    87.     public void Replay()
    88.     {
    89.        
    90.         endGame.SetActive(false);
    91.         mainMenu.SetActive(true);
    92.         gameOver = false;
    93.         newZombie = Instantiate(zombie) as GameObject;
    94.        
    95.     }
    96.  
     
  2. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    38,744
    I'll bet that something isn't right about the "singleton-ness" of the above. See bottom of this post.

    To prove what the problem is, use this approach:

    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
    - you're getting an error or warning and you haven't noticed it in the console window

    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 supply a second argument to Debug.Log() and when you click the message, it will highlight the object in scene, such as
    Debug.Log("Problem!",this);


    If your problem would benefit from in-scene or in-game visualization, Debug.DrawRay() or Debug.DrawLine() can help you visualize things like rays (used in raycasting) or distances.

    You can also call Debug.Break() to pause the Editor when certain interesting pieces of code run, and then study the scene manually, looking for all the parts, where they are, what scripts are on them, etc.

    You can also call GameObject.CreatePrimitive() to emplace debug-marker-ish objects in the scene at runtime.

    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, such as this answer or iOS: https://forum.unity.com/threads/how-to-capturing-device-logs-on-ios.529920/ or this answer for Android: https://forum.unity.com/threads/how-to-capturing-device-logs-on-android.528680/

    Another useful approach is to temporarily strip out everything besides what is necessary to prove your issue. This can simplify and isolate compounding effects of other items in your scene or prefab.

    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

    When in doubt, print it out!(tm)

    Note: the
    print()
    function is an alias for Debug.Log() provided by the MonoBehaviour class.

    You must find a way to get the information you need in order to reason about what the problem is.

    ----------------------------------------------------

    I prefer one of these two patterns for GameManagers:

    ULTRA-simple static solution to a GameManager:

    https://forum.unity.com/threads/i-need-to-save-the-score-when-the-scene-resets.1168766/#post-7488068

    https://gist.github.com/kurtdekker/50faa0d78cd978375b2fe465d55b282b

    OR for a more-complex "lives as a MonoBehaviour" solution...

    Simple Singleton (UnitySingleton):

    Some super-simple Singleton examples to take and modify:

    Simple Unity3D Singleton (no predefined data):

    https://gist.github.com/kurtdekker/775bb97614047072f7004d6fb9ccce30

    Unity3D Singleton with a Prefab (or a ScriptableObject) used for predefined data:

    https://gist.github.com/kurtdekker/2f07be6f6a844cf82110fc42a774a625

    These are pure-code solutions, do not put anything into any scene, just access it via .Instance!

    If it is a GameManager, when the game is over, make a function in that singleton that Destroys itself so the next time you access it you get a fresh one, something like:

    Code (csharp):
    1. public void DestroyThyself()
    2. {
    3.    Destroy(gameObject);
    4.    Instance = null;    // because destroy doesn't happen until end of frame
    5. }
    There are also lots of Youtube tutorials on the concepts involved in making a suitable GameManager, which obviously depends a lot on what your game might need.
     
    roopesh23 likes this.