Search code examples
unity-game-enginedestroyobject-pooling

Pooled GameObject in Unity destroys itself after SetActive if Force is applied


When I retrieve an object from a list of created objects and reactivate it, it destroys itself, but only if I have force applied to start it moving. If I never apply force, everything works as intended and I can keep activating the object over and over.

  • I've tried putting a debug.log in the OnCollision and it isn't colliding with anything.
  • As said above, if I never initiate speed, the rest works fine.
  • When speed is applied, the first projectile works, the second destroys itself.
  • I've tried manually activating them instead of by code. Same result.
  • Exception: If I manually activate/deactivate objects myself through the inspector, they work if I only have 1 shot in the pool.
  • The one shot rule doesn't work if I do it through code. It breaks even if I only have one shot.
  • All the code worked when I wasn't using pooling.

Spawn code:

    void CreateBullet(int GunID)
{
    GameObject ShotFired = Guns[GunID].GetComponent<Weapon>().FireWeapon();

    if (ShotFired == null)
    {
        ShotFired = Instantiate(Guns[GunID].GetComponent<Weapon>().Projectile,Guns[GunID].gameObject.transform);
        Physics.IgnoreCollision(ShotFired.GetComponent<SphereCollider>(), Guns[GunID].GetComponentInParent<CapsuleCollider>());
        Guns[GunID].GetComponent<Weapon>().AmmoPool.Add(ShotFired);
    }


    ShotFired.transform.position = Guns[GunID].transform.position; 
    ShotFired.transform.rotation = Guns[GunID].transform.rotation;

    ShotFired.SetActive(true);
}

Projectile Code:

 using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Mirror;

public class Projectile : NetworkBehaviour
{
    public float Speed;
    public float LifeTime;
    public float DamagePower;

    public GameObject ExplosionFX;

    // Start is called before the first frame update
    void Start()
    {
        GetComponent<Rigidbody>().AddRelativeForce(Vector3.up * Speed, ForceMode.VelocityChange);
        StartCoroutine(DeactivateSelf(5.0f));
    }

    private void OnDestroy()
    {
        Debug.Log("WHY!");
    }

    IEnumerator DeactivateSelf(float Sec)
    {
        yield return new WaitForSeconds(Sec);
        Explode();
    }

    private void OnCollisionEnter(Collision collision)
    {
        if (collision.gameObject.GetComponentInChildren<Vehicle>())
        {
            collision.gameObject.GetComponentInChildren<Vehicle>().CmdTakeDamage(DamagePower);
        }

        Explode();
    }

    void Explode()
    {
        GameObject ExplosionEvent = Instantiate(ExplosionFX, this.transform.position, Quaternion.identity);
        NetworkServer.Spawn(ExplosionEvent);
        GetComponent<Rigidbody>().AddRelativeForce(Vector3.zero);

        gameObject.SetActive(false);
    }
}

Any thoughts welcome. Thanks in advance!


Solution

  • In case anyone else stumbles across this, here's what happened and why assigning a movement speed to the object was what caused the issue.

    My projectiles had a 'trailrenderer' on them.

    By default 'Autodestruct' is true.

    Autodestruct does not destruct the trail, but the game object when the trail disappears. So if you disable anything that had a trail, and activated it through movement, when the object stops moving (say to reposition in an object pool) it will destroy the parent object.

    If the object never moves, it never generates a trail, and never needs to be destroyed.

    To fix, just uncheck autodestruct.

    https://docs.unity3d.com/ScriptReference/TrailRenderer-autodestruct.html