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. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice

Question How To Determine Why I'm Getting Multiple Powerups When Picking Up 1

Discussion in '2D' started by hinklejoe, Oct 17, 2023.

  1. hinklejoe

    hinklejoe

    Joined:
    Apr 21, 2021
    Posts:
    18
    I'm running into an issue where my powerup pickups are being duplicated so when I grab one weapon upgrade I end up getting 2. I believe my problem is that I have multiple box colliders and multiple collisions are happening before the object is destroyed but I'm not sure how to determine if this is correct. My problem outline is below.

    1. I have only verified this on pickups. It does not appear to be an issue with bullets/missiles, only powerups.

    2. The powerup is the trigger. The player is not a trigger.

    3. The player ship has around 10 box colliders to define it's shape. If this is the wrong way to do this please let me know.

    4. I am including my code for the pickups here. All pickups use the same script

    Code (CSharp):
    1. public class PowerUpBehavior : MonoBehaviour
    2. {
    3.     // Power Up Type
    4.     public string powerUpType;
    5.  
    6.     // The amount of the value to increase - This is not used
    7.     public int incrementValue;
    8.  
    9.     // Direction & Speed
    10.     private Vector3 objectDirection = new Vector3(-1f,0f,0f);
    11.     public float moveSpeed = .5f;
    12.  
    13.     void FixedUpdate()
    14.     {
    15.         // Move the powerup from right to left slowly
    16.         transform.position += objectDirection * moveSpeed * Time.deltaTime;
    17.     }
    18.  
    19.     void OnTriggerEnter2D(Collider2D hitInfo)
    20.     {
    21.         if (hitInfo.gameObject.tag != "Enemy" || hitInfo.gameObject.tag != "TileMap")
    22.         {
    23.             Destroy(gameObject);
    24.         }
    25.     }
    26. }
    5. I am including my code for the player to add the pickup.

    Code (CSharp):
    1.  void OnTriggerEnter2D(Collider2D hitInfo)
    2.     {
    3.         if (hitInfo.gameObject.tag == "Enemy Bullets" || hitInfo.gameObject.tag == "Level Weapon")
    4.         {
    5.             if (!isTempInvincible)
    6.             {
    7.                 EnemyBulletDefault hitObject = hitInfo.GetComponent<EnemyBulletDefault>();
    8.                 HealthRemove(hitObject.bulletDamage);
    9.  
    10.                 // string myHealthString = "-" + hitObject.bulletDamage + " Health";
    11.                 // DisplayText(myHealthString, Color.red);
    12.  
    13.                 // Play Sound Effect For Being Hit
    14.                 soundSceneSound.PlayOneShot(soundPlayerHit, HUDController.sfxVolume);
    15.             }
    16.         }
    17.  
    18.         if (hitInfo.gameObject.tag == "Coin")
    19.         {
    20.             // Get the coin value  
    21.             CoinBehavior hitObject = hitInfo.GetComponent<CoinBehavior>();
    22.  
    23.             // Update the HUD & Save The Data To Player Prefs
    24.             refHUDController.UpdatePlayerCurrency(hitObject.coinValue);
    25.  
    26.             // Display data above the player
    27.             string tokenString = "+" + hitObject.coinValue + " Token";
    28.             DisplayText(tokenString, Color.yellow);
    29.  
    30.             // Play Sound Effect For Coin
    31.             soundSceneSound.PlayOneShot(soundCoinEffect, HUDController.sfxVolume);
    32.         }
    33.  
    34.         // This area is where values are incremented.  No lvl system exists, just increment the starting variables as you play
    35.         if (hitInfo.gameObject.tag == "Power Up")
    36.         {
    37.             PowerUpBehavior hitObject = hitInfo.GetComponent<PowerUpBehavior>();
    38.  
    39.             Debug.Log("Powerup Found: " + hitObject.powerUpType);
    40.  
    41.             if (hitObject.powerUpType == "FirePower")
    42.             {
    43.                 bulletDamage += 1;
    44.                 DisplayText("+1 Damage", Color.green);
    45.  
    46.                 Debug.Log("Bullet Damage: " + bulletDamage);
    47.  
    48.                 // Update the player pref value
    49.                 if (playerNumber == 1)
    50.                 {
    51.                     int myValue = PlayerPrefs.GetInt("p1FirePower") + 1;
    52.                     PlayerPrefs.SetInt("p1FirePower", myValue);
    53.                 }
    54.                 else if (playerNumber == 2)
    55.                 {
    56.                     int myValue = PlayerPrefs.GetInt("p2FirePower") + 1;
    57.                     PlayerPrefs.SetInt("p2FirePower", myValue);
    58.                 }
    59.             }
    60.             else if (hitObject.powerUpType == "Health")
    61.             {
    62.                 totalHealth += 1;
    63.                 health += 3;
    64.  
    65.                 Debug.Log("Health: " + health + " Total Health: " + totalHealth);
    66.  
    67.                 // If health goes over total health fix it before updating everything.
    68.                 if (health > totalHealth)
    69.                 {
    70.                     health = totalHealth;
    71.                 }
    72.  
    73.                 // Update the HUD health + total health
    74.                 healthSlider.maxValue = totalHealth;
    75.                 healthSlider.value = health;
    76.  
    77.                 // Display a message above the ship
    78.                 DisplayText("+3 Health", Color.green);
    79.  
    80.                 // Update the player pref value
    81.                 if (playerNumber == 1)
    82.                 {
    83.                     int myValue = PlayerPrefs.GetInt("p1Health") + 1;
    84.                     PlayerPrefs.SetInt("p1Health", myValue);
    85.                 }
    86.                 else if (playerNumber == 2)
    87.                 {
    88.                     int myValue = PlayerPrefs.GetInt("p2Health") + 1;
    89.                     PlayerPrefs.SetInt("p2Health", myValue);
    90.                 }
    91.             }
    92.             else if (hitObject.powerUpType == "SpecialTime")
    93.             {
    94.                 specialFireTime += 1f;
    95.                 DisplayText("+1 Special Time", Color.green);
    96.  
    97.                 // Update the player pref value
    98.                 if (playerNumber == 1)
    99.                 {
    100.                     int myValue = PlayerPrefs.GetInt("p1SpecialTime") + 1;
    101.                     PlayerPrefs.SetInt("p1SpecialTime", myValue);
    102.                 }
    103.                 else if (playerNumber == 2)
    104.                 {
    105.                     int myValue = PlayerPrefs.GetInt("p2SpecialTime") + 1;
    106.                     PlayerPrefs.SetInt("p2SpecialTime", myValue);
    107.                 }
    108.             }
    109.             else if (hitObject.powerUpType == "Missle")
    110.             {
    111.                 numOfMissiles += 1;
    112.                 DisplayText("+1 Missile", Color.green);
    113.  
    114.                 // Update the player pref value
    115.                 if (playerNumber == 1)
    116.                 {
    117.                     int myValue = PlayerPrefs.GetInt("p1Missile") + 1;
    118.                     PlayerPrefs.SetInt("p1Missile", myValue);
    119.                 }
    120.                 else if (playerNumber == 2)
    121.                 {
    122.                     int myValue = PlayerPrefs.GetInt("p2Missile") + 1;
    123.                     PlayerPrefs.SetInt("p2Missile", myValue);
    124.                 }
    125.             }
    126.             else if (hitObject.powerUpType == "Speed")
    127.             {
    128.                 moveSpeed += .5f;
    129.                 DisplayText("Speed Up", Color.green);
    130.  
    131.                 // Update the player pref value
    132.                 if (playerNumber == 1)
    133.                 {
    134.                     float myValue = PlayerPrefs.GetFloat("p1Speed") + .5f;
    135.                     PlayerPrefs.SetFloat("p1Speed", myValue);
    136.                 }
    137.                 else if (playerNumber == 2)
    138.                 {
    139.                     float myValue = PlayerPrefs.GetFloat("p2Speed") + .5f;
    140.                     PlayerPrefs.SetFloat("p2Speed", myValue);
    141.                 }
    142.             }
    143.             else if (hitObject.powerUpType == "SpAttack")
    144.             {
    145.                 // Update total Super.  UpdatePlayerSuperPower will do the logic for player
    146.                 UpdatePlayerSuperPower(1);
    147.                 DisplayText("+1 Super", Color.green);
    148.             }
    149.  
    150.             // Play The Power Up Sound Effect
    151.             soundSceneSound.PlayOneShot(soundPowerUpEffect, HUDController.sfxVolume);
    152.         }
    153.     }
    6. I can see the debug code run multiple times for a pickup despite there only being 1 item to pickup. Below is output for 1 pickup I manually placed on the scene to test with.

    Bullet Damage: 2
    UnityEngine.Debug:Log (object)
    ReconShipBehavior:OnTriggerEnter2D (UnityEngine.Collider2D) (at Assets/Player/Scripts/ReconShipBehavior.cs:521)

    Powerup Found: FirePower
    UnityEngine.Debug:Log (object)
    ReconShipBehavior:OnTriggerEnter2D (UnityEngine.Collider2D) (at Assets/Player/Scripts/ReconShipBehavior.cs:514)

    Bullet Damage: 3
    UnityEngine.Debug:Log (object)
    ReconShipBehavior:OnTriggerEnter2D (UnityEngine.Collider2D) (at Assets/Player/Scripts/ReconShipBehavior.cs:521)

    Powerup Found: FirePower
    UnityEngine.Debug:Log (object)
    ReconShipBehavior:OnTriggerEnter2D (UnityEngine.Collider2D) (at Assets/Player/Scripts/ReconShipBehavior.cs:514)

    Has anyone seen this before or know of a proper way to troubleshoot multiple pickups like this? I'm thinking about converting the code to a coroutine and then putting a bool var to keep anything from updating while the coroutine is running. I've done this before and have no problems doing it, I just want to understand why it appears multiple colliders find the object before it destroys itself.
     
  2. Cornysam

    Cornysam

    Joined:
    Feb 8, 2018
    Posts:
    1,354
    I'd say the easiest way to test if it is a collider issue is to replace those 10 colliders with one simple circle or box collider. Test if that still calls multiple times or not. If that fixes the issue, then you may want to look at composite colliders or w/e they're called (the ones where they are funky shapes)
     
  3. hinklejoe

    hinklejoe

    Joined:
    Apr 21, 2021
    Posts:
    18
    Your test sounds good and I'll test it here in a little bit.

    Are you talking about the physics shapes you can generate on the image? I've done that for tile maps but didn't know you could do that with player sprites. I'll look that up.
     
  4. hinklejoe

    hinklejoe

    Joined:
    Apr 21, 2021
    Posts:
    18
    I've done some basic testing and it appears that you are correct. If I go into the asset image and into the sprite editor I can generate a physics shape. Then I attach a Polygon Collider 2D and I have not seen the problem repeat itself yet.

    One thing I noticed is that even though my code all appears to be working in OnTriggerEnter2D. I am not seeing my Debug.Log statements show up in the console anymore. I'll need to do some further reading and testing to make sure I understand what's going on.

    Thank you for your assistance.
     
  5. Cornysam

    Cornysam

    Joined:
    Feb 8, 2018
    Posts:
    1,354
    Very strange that everything is working but not printing the log statements anymore. Are all of your powerups working now?
     
  6. hinklejoe

    hinklejoe

    Joined:
    Apr 21, 2021
    Posts:
    18
    Yeah the value is incrementing both the variable and the player pref. Everything looks good.

    Now that I'm typing this out I wonder if I just need to reboot my PC. I've had the editor do weird things after I have it open for a while.
     
  7. hinklejoe

    hinklejoe

    Joined:
    Apr 21, 2021
    Posts:
    18
    I want to post a final update to this issue.

    I found that this issue exists anywhere I have multiple colliders configured on a object. For enemies the problem comes up when an AOE attack from a missile hits multiple colliders. For my pickups it appears the amount of code was causing it to delay and get picked up by multiple colliders. By going into the sprite editor and setting a physics shape for all frames I not only fix this problem but I properly set the animations to change collider shapes as well.
     
  8. LoupAndSnoop

    LoupAndSnoop

    Joined:
    Jun 23, 2023
    Posts:
    34
    For this sort of thing, you might want to try a composite collider to make the process not terrible.

    It’s probably also a good idea to use something like a command pattern: Durring the OnTriggerCalback step, collect a bunch of requests for powerups we touched. Then new WaitForFixedUpdate so you can sift through all powerup requests that happened that frame.

    This is probably better because you might have multiple powerups being touched at once, or touch enemy at same time as powerup etc, or touching two bullets of different dmg on the same frame etc.