Search Unity

[Solved]Pooled bullets deactivates mid screen, not off screen at deactivation point

Discussion in 'Scripting' started by benvanj, Oct 16, 2018.

  1. benvanj

    benvanj

    Joined:
    Jun 26, 2018
    Posts:
    116
    Hi Guys, I need your help please....

    Background:
    my android game is an infinite runner that spawns androids attacking ...
    the player runs automatic... can roll to avoid bullets, jump to other platforms, shoot bullets to kill androids and have a bomb that you pick up and shoot to clear the screen...
    also the speed increases over a span of time...When the game speeds up the player bullets also speeds up
    Because it is an android game, i have object poolers running bullets, platforms and enemies..

    the problem...
    after the speed of the game has increased a couple of times...(i think 3 times)... my player's bullets don't go off screen and deactivate(deactivation point is off screen)... it deactivates mid screen... and I am not sure how to find the problem, please help

    Bullet Deactivation script:

    Code (CSharp):
    1. public class BulletDestroyer : MonoBehaviour
    2. {
    3.     private GameObject BulletDesPoint;
    4.    
    5.     // Update is called once per frame
    6.     void Update()
    7.     {
    8.         BulletDesPoint = GameObject.Find("BulletDesPoint");
    9.  
    10.         if (transform.position.x > BulletDesPoint.transform.position.x)
    11.         {
    12.            gameObject.SetActive(false);
    13.         }
    14.     }
    15.     private void OnTriggerEnter2D(Collider2D collision)
    16.     {
    17.         if (collision.tag == "Enemy")
    18.         {
    19.             gameObject.SetActive(false);
    20.         }
    21.     }
    22. }
    Bullet Pooler script ... I have 15 Bullets pooled

    Code (CSharp):
    1. public class ObjPooler : MonoBehaviour
    2. {
    3.     public GameObject PooledObject;
    4.  
    5.     public int PooledAmount;
    6.  
    7.     List<GameObject> PooledObjects;
    8.  
    9.     // Use this for initialization
    10.     void Start()
    11.     {
    12.         PooledObjects = new List<GameObject>();
    13.  
    14.         for (int i = 0; i < PooledAmount; i++)
    15.         {
    16.             GameObject obj = Instantiate(PooledObject);
    17.             obj.SetActive(false);
    18.             PooledObjects.Add(obj);
    19.         }
    20.     }
    21.  
    22.     public GameObject GetPooledObject()
    23.     {
    24.         for (int i = 0; i < PooledObjects.Count; i++)
    25.         {
    26.             if (!PooledObjects[i].activeInHierarchy)
    27.             {
    28.                 return PooledObjects[i];
    29.             }
    30.         }
    31.  
    32.         GameObject obj = Instantiate(PooledObject);
    33.         obj.SetActive(false);
    34.         PooledObjects.Add(obj);
    35.         return obj;
    36.     }
    37. }

    Thanks in advance
     
  2. Joe-Censored

    Joe-Censored

    Joined:
    Mar 26, 2013
    Posts:
    11,847
    Is "BulletDesPoint.transform.position.x" the value you expect it to be to be off the screen? I'd guess that it is closer to the middle of the screen that you think it is.

    Also, you're negating any performance benefit of the object pooler by calling GameObject.Find on every bullet every single frame. You should call it once when you set up the object pooler and pass the cached reference to the bullet when you instantiate the bullet.
     
  3. benvanj

    benvanj

    Joined:
    Jun 26, 2018
    Posts:
    116
    Hi, Yes the BulletDesPoint.transform.position.x is off screen I've checked it a couple of times... it is also a child of the Main Camera so it stays off screen.....

    I have just recently moved the "GameObject.Find" to the Update functions... as I thought that it would solve my problem... my theory was that if it was done in the Start Function that it kept the coordinates right at that time... so i wanted it to update....
     
  4. ADNCG

    ADNCG

    Joined:
    Jun 9, 2014
    Posts:
    994
    Care to share the script that calls GetPooledObject?
     
  5. Joe-Censored

    Joe-Censored

    Joined:
    Mar 26, 2013
    Posts:
    11,847
    But are you moving the camera? And if you are, are you moving the camera in LateUpdate which is pretty typical? If so BulletDesPoint.transform.position can actually be a position within the view of the camera during Update if the camera is moved in LateUpdate. If you are moving the camera during Update the same can be true if the camera movement happens to occur after your bullets run their Update methods.

    Personally, I'd just try moving BulletDesPoint far away from the edge of the screen so as not to worry about this. Probably a simple work around to this.
     
    ADNCG likes this.
  6. Joe-Censored

    Joe-Censored

    Joined:
    Mar 26, 2013
    Posts:
    11,847
    If the problem is the timing of the camera movement, you could give yourself more work by delaying the check if you should disable the bullets until after the camera has moved. Have the camera movement code actually call the methods to check if the bullets should be disabled instead of having the bullets do it themselves.

    I do something similar when positioning some UI windows above characters in my game after my camera has moved that frame in LateUpdate. What I do is just have every UI window register a delegate with the camera script to be called after the camera moves, which then properly positions the UI window above the character. Would be similar for testing if a bullet should be deactivated after the camera moves.
     
    benvanj likes this.
  7. benvanj

    benvanj

    Joined:
    Jun 26, 2018
    Posts:
    116

    Code (CSharp):
    1. public GameObject GetPooledObject()
    2.     {
    3.         for (int i = 0; i < PooledObjects.Count; i++)
    4.         {
    5.             if (!PooledObjects[i].activeInHierarchy)
    6.             {
    7.                 return PooledObjects[i];
    8.             }
    9.         }
    10.  
    11.         GameObject obj = Instantiate(PooledObject);
    12.         obj.SetActive(false);
    13.         PooledObjects.Add(obj);
    14.         return obj;
    15.     }
     
  8. ADNCG

    ADNCG

    Joined:
    Jun 9, 2014
    Posts:
    994
    No no, I mean the script that calls this method. Somewhere you're calling GetPooledObject() to get your bullet.

    I was curious since it's possible that, if your firing method fires multiple bullets at once or over a short period of time, you could be caching a few bullet instances at once.

    The problem would be that, unless you set the bullet to active right after caching it and before calling for the next bullet, GetPooledObject will return the same bullet as it did before, since it relies on the object being active.

    Then, let's say your method fires 3 bullets over a second, it would look like the first bullet is despawning as the second is fired, but really it'd just be that the second bullet IS the first bullet, if that makes any sense?

    Anyways, it might be a stretch, it's most likely a cam issue like @Joe-Censored pointed
     
    benvanj likes this.
  9. benvanj

    benvanj

    Joined:
    Jun 26, 2018
    Posts:
    116

    I moved it about a screen's length and still have the same problem...
    the main camera is following the Player... here is the script...

    Code (CSharp):
    1. public class CameraController : MonoBehaviour
    2. {
    3.     private PlayerSC Player;
    4.  
    5.     private Vector3 lastPlayerPosition;
    6.     private float distanceToMove;
    7.  
    8.  
    9.     // Use this for initialization
    10.     void Start ()
    11.     {
    12.         Player = FindObjectOfType<PlayerSC>();
    13.         lastPlayerPosition = Player.transform.position;
    14.        
    15.     }
    16.    
    17.     // Update is called once per frame
    18.     void Update ()
    19.     {
    20.         distanceToMove = Player.transform.position.x - lastPlayerPosition.x;
    21.  
    22.         transform.position = new Vector3(transform.position.x + distanceToMove, transform.position.y, transform.position.z);
    23.  
    24.         lastPlayerPosition = Player.transform.position;
    25.        
    26.     }
    27. }
     
  10. benvanj

    benvanj

    Joined:
    Jun 26, 2018
    Posts:
    116

    Thanks... I get what you are saying... the getpooled object, is inside a big script attached to my player... but here is the code:

    Code (CSharp):
    1. public void Fire()
    2.     {
    3.         if (theScoreManager.AmmoCount >= 1)
    4.         {
    5.             GameObject newItem = theObjectPool.GetPooledObject();
    6.  
    7.             newItem.transform.position = FirePos.transform.position;
    8.             newItem.transform.rotation = FirePos.transform.rotation;
    9.             newItem.SetActive(true);
    10.             theScoreManager.AmmoCount -= 1;
    11.             PlayerFire.Play();
    12.         }
    13.     }
     
  11. benvanj

    benvanj

    Joined:
    Jun 26, 2018
    Posts:
    116

    I also thought of that but I am not sure how to trouble shoot it... My Object Pooler for the bullets was only 5, but i have increased it to 15 to make sure that, that would not be the case.... UNLESS it is still doing so even though my pool is bigger... but how do fix that??????
     
  12. ADNCG

    ADNCG

    Joined:
    Jun 9, 2014
    Posts:
    994
    Eh, unrelated but you're incrementing your camera position by the delta of the player's current position and its last position, and this instantly. You can simplify your update with this :
    Code (CSharp):
    1. transform.position = new Vector3(Player.transform.position.x, transform.position.y, transform.position.z);
    Nah, this won't be the problem. You pool handles the generation of a new object if all the available instances are busy.
     
    benvanj likes this.
  13. benvanj

    benvanj

    Joined:
    Jun 26, 2018
    Posts:
    116
    Thanks....

    I have a question then... so the script attached to my player is 361 lines long... wouldn't it be better to write smaller scripts for the different processes and attache them all to my Player??
     
  14. Serinx

    Serinx

    Joined:
    Mar 31, 2014
    Posts:
    788
    Do you have any other scripts which could be destroying/deactivating the bullet? Perhaps a script on the bullet itself?

    You could add a debug.Log before you deactivate the bullets in BulletDestroyer
    Now while playing, you should see your debug.log displayed, and if you dont, you know that something else is deactivating the bullets.

    You could also change your "off screen" detection to something more basic to check if that's the problem, e.g:

    Code (CSharp):
    1.  
    2. float screenWidth = 100f;
    3. if (transform.position.x > Camera.main.transform.position.x + screenWidth)
    4. {
    5.      gameObject.setActive(false);
    6. }
     
  15. benvanj

    benvanj

    Joined:
    Jun 26, 2018
    Posts:
    116
    The BulletDestroy script is on the bullet... but You are right, there could be some thing else deactivating the bullet...


    I will try this, thank you...
     
  16. benvanj

    benvanj

    Joined:
    Jun 26, 2018
    Posts:
    116
    Hi guys, thank you very much for all the help.... the problem is sorted...

    there was a script called: Mover that I've used to move the Rigidbodies of the bullets.... I would use a positive to move the "playerbullets" and a negative to move the "enemybullets"... this script also had deactivate functions in it... after splitting the two scripts the problem is solved
     
    Serinx likes this.