Home > OS >  disabling gameObjects after seconds using object pooling and coroutines
disabling gameObjects after seconds using object pooling and coroutines

Time:06-28

I'm developing a simple VR shooter in unity, i use object pooling for the bullets (Lasers here) this is the ObjectPool script, here i istantiate a list of bullets in the start() method and disable them.

public class ObjectPool : MonoBehaviour   
{
    public static ObjectPool instance;
    private List<GameObject> pooledObject = new List<GameObject>();
    private int amountToPool = 20;
    [SerializeField] private GameObject laserPrefab;

  

private void Awake()
{
    if (instance == null)
    {
        instance = this;
    }
}
// Start is called before the first frame update
void Start()
{
    for (int i = 0; i < amountToPool; i  )
    {
        GameObject obj = Instantiate(laserPrefab);
        obj.SetActive(false);
        pooledObject.Add(obj);
    }
}

public GameObject GetPooledObject()
{
    for (int i = 0; i < pooledObject.Count; i  )
    {
        if (!pooledObject[i].activeInHierarchy)
        {
            return pooledObject[i];
        }
    }
    return null;
}

}

This is the Script attached to the gun where i get the pooled bullet and set it to active

   public class FireLaserGun : MonoBehaviour
{        
    public GameObject laserBeamModel;
    public Transform laserSpawnPoint;
   
// Start is called before the first frame update
public void FireGun()
{
    GameObject laser = ObjectPool.instance.GetPooledObject();

    if (laser != null)
    {
        laser.transform.position = laserSpawnPoint.position;
        laser.transform.rotation = laserSpawnPoint.rotation;
        laser.SetActive(true);
      
        Debug.Log("BOOM");
    }
    else
    {
        Debug.Log("Laser is null");
    }                
}
}

I'm trying to disable the bullet after two seconds was fired using a coroutine in the script that moves the bullets:

public class LaserBeamMove : MonoBehaviour
{
    private Rigidbody rb;
    public float thrust = 10.0f;
    float waitTime = 2.0f;
    private IEnumerator coroutine;

// Start is called before the first frame update

void Start()
{
    rb = GetComponent<Rigidbody>();
    coroutine = WaitToDisable(waitTime);
    StartCoroutine(coroutine);
}

void FixedUpdate()
{
    rb.velocity = transform.forward * thrust;        
}
private IEnumerator WaitToDisable(float waitTime)
{
    yield return new WaitForSeconds(waitTime);
    gameObject.SetActive(false);
    Debug.Log("bullet disabled after "   waitTime   "seconds");

}
}

Strangely first seconds of the game everything seems fine, all the bullets start as inactive and every bullet becomes active when fired and inactive after two seconds. After some seconds bullets dont become inactive anymore (actually only some of them do). this is a screenshot of the console log, when i fire i print "BOOM" and when a bullet becomes inactive i print "bullet disabled after 2 seconds" As you can see this down't work for every bullet and i don't understand why. Am i doing something wrong with the courutine?

https://i.stack.imgur.com/rMJgg.png

CodePudding user response:

Take the code you have in void Start() and move it to a new void OnEnable. The reason is that Start is only called once, the first time the object holding the script is enabled (e.g when the scene loads, when you instantiate a bullet etc), OnEnable is called every time the object is enabled, which is what you want here. You could also use Awake but IMHO that's best kept separately for initialisation stuff only so you can keep the code tidy and separate out game logic from init logic.

CodePudding user response:

You probably want to destroy the game objects so they (and their coroutines) aren't re-used by Unity - this is just from personal experience with weird bugs.

  • Related