Search Unity

Question Trying to respawn pickups after they're all gone

Discussion in 'Scripting' started by aldenchappell, Sep 27, 2022.

  1. aldenchappell

    aldenchappell

    Joined:
    Sep 11, 2022
    Posts:
    3
    I'm attempting to make my pickups respawn after the player has picked all of them up. I have tried several different ways of wording my "respawn" code, and cannot seem to get it to work. I am a beginner so any tips/advice you can supply me with is much appreciated!


    Here is my script:


    Code (CSharp):
    1. public class Player : MonoBehaviour
    2. {
    3.     public GameObject blueCube, redCube, greenCube; //declares pickup objects
    4.     public float speed = 10f; // declares float speed and assigns a speed
    5.     private Rigidbody rb; // declares a rigidbody component for player
    6.     private Renderer playerRenderer; // declares a renderer component for player
    7.     private int pickupTotal; //declares an int for the total number of pickups
    8.     private int pickupCounter; //declares an int for the pickup counter
    9.  
    10.  
    11.  
    12.     // Start is called before the first frame update
    13.     void Start()
    14.     {
    15.         rb = GetComponent<Rigidbody>(); // calling rigidbody component for player's rigidbody
    16.         playerRenderer = GetComponent<Renderer>(); // calls renderer component for raycasting to paint puddles
    17.         //GetComponent<Renderer>().material.color = colorBlue; // calls color component to load player's color at start
    18.         pickupTotal = 10; // gives value to the total number of pickups
    19.         pickupCounter = pickupTotal; // gives the value of the pickup total to the pickup counter
    20.         GenerateAllPickups(); // calls generateallpickups method
    21.     }
    22.  
    23.  
    24.     void GeneratePickup()
    25.     {
    26.         int randomCubeNum = Random.Range(1, 4); // declares and initializes range of the 3 different cubes
    27.         Vector3 spawnPos = new Vector3(Random.Range(-10, 10), .75f, Random.Range(10, -10)); //initializes a new vector3 for pickups to spawn randomly within boundaries
    28.         switch (randomCubeNum) // starts a switch statement for 3 different cubes
    29.         {
    30.             case (1):
    31.                 Instantiate(blueCube, spawnPos, Quaternion.identity); //case for blue cube instantiation
    32.                 break;
    33.             case (2):
    34.                 Instantiate(redCube, spawnPos, Quaternion.identity); // case for red cube instantiation
    35.                 break;
    36.             case (3):
    37.                 Instantiate(greenCube, spawnPos, Quaternion.identity); // case for greencube instantiation
    38.                 break;
    39.             default:
    40.                 Debug.Log("There was an error with the random number generation."); //default message if all cases do not apply
    41.                 break;
    42.         }
    43.     }
    44.  
    45.  
    46.     void GenerateAllPickups()
    47.     {
    48.         int count = 0;
    49.         while (pickupCounter > count) // while the pickup counter is greater than 0
    50.         {
    51.             GeneratePickup(); // calls generatepickup method
    52.             pickupCounter--; // decrements pickups when collected
    53.         }
    54.  
    55.     }
    56.  
    57.     void HandleClick()
    58.     {
    59.         if (Input.GetMouseButtonUp(0)) // if the left mouse button is clicked
    60.         {
    61.             RaycastHit hit; // declares and initializes a raycasthit for paint puddles
    62.             Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition); // declares and initializes a ray to cast a ray wherever the mouse is clicked
    63.             if (Physics.Raycast(ray, out hit, 50.0f)) // if raycast is present, call ray, call hit, for a value of 50.0
    64.             {
    65.                 if (hit.collider.CompareTag("paintPuddle")) // if the red puddle tag is clicked
    66.                 {
    67.                     playerRenderer.material.color = hit.collider.gameObject.GetComponent<Renderer>().material.color; // get the players renderer color, change to whichever puddle is clicked
    68.                 }
    69.             }
    70.         }
    71.     }
    72.  
    73.  
    74.     void OnTriggerEnter(Collider other)
    75.     {
    76.         if (other.CompareTag("Pickup")) //if the pickup matches the color
    77.         {
    78.             Color pickupColor = other.gameObject.GetComponent<Renderer>().material.color; //declares a color variable and gets the color renderer component
    79.             if (pickupColor == playerRenderer.material.color) // if the color of the pickup matches the color of the players color renderer
    80.             {
    81.                 Destroy(other.gameObject); // destroy the pickup
    82.                 pickupCounter--; // decrement the pickup counter
    83.                 if (pickupCounter <= 0) // if the pickup counter is less than or equal to 0
    84.                 {
    85.                     GenerateAllPickups(); // call the generate all pickups method
    86.                     pickupCounter = pickupTotal; //reset the pickup counter back to the pickup total
    87.                 }
    88.             }
    89.         }
    90.     }
    91.  
    92.     // Update is called once per frame
    93.     void FixedUpdate()
    94.     {
    95.         float moveHorizontal = Input.GetAxis("Horizontal"); // declares and initializes a float to get the players input on the horizontal axis
    96.         float moveVertical = Input.GetAxis("Vertical"); // declares and initializes a float to get the players input on the vertical axis
    97.  
    98.         rb.AddForce(new Vector3(moveHorizontal, 0, moveVertical) * speed); // gets the (rb)rigidbody component, adds force, adds a new vector3 for the horizontal
    99.                                                                            // and vertical input, and keeps the rigidbody at 0 on the y-axis and gets the speed
    100.                                                                            // from the class scoped speed variable        
    101.     }
    102.  
    103.     void Update()
    104.     {
    105.         HandleClick(); //calls the handleclick method to raycast paint puddles
    106.     }
    107.  
    108. }
     
    Last edited: Sep 27, 2022
  2. mopthrow

    mopthrow

    Joined:
    May 8, 2020
    Posts:
    348
    On line 49 while(pickupCounter > count) will never be true other than the first time you call GenerateAllPickups().

    The first time you call GenerateAllPickups() your pickupCounter was set to 10 on line 19, with the function called straight after that on line 20. The while loop on 49 reads while(10 > 0). Perfectly fine. When this loop is finished, pickupCounter has been decremented to 0 as per line 52.

    When you call GenerateAllPickups() again on line 85, your pickupCounter is -1 as per the decrement on line 82.

    The while condition on 49 in this case reads while(pickupCounter > count) or while(-1 > 0). This is never true, so your GeneratePickup() on 51 inside the loop will never run.

    As a fix, how about changing 82 to increment instead (++ instead of --) and setting line 83's condition to be >0 instead of <= 0. Now when your GenerateAllPickups() runs on 85, you'll have a positive pickupCount and loop should run. Although I'm not sure that's what you want, as it'll respawn one pickup every time you pick up and destroy an existing one.
     
    Last edited: Sep 27, 2022
    aldenchappell likes this.
  3. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    38,674
    Welcome to debugging! Here is how to get started:

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

    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.
     
  4. aldenchappell

    aldenchappell

    Joined:
    Sep 11, 2022
    Posts:
    3
    Ohhhh I get it now. I confused myself in my HandleClick() when I called the pickupCounter to decrement. I changed it to while(count < 10) and count--; and that fixed it! Thank you.
     
    mopthrow likes this.