First shot projectile is not visible using object pooling

I’ve been fiddling with object pooling lately.
I have: A gun that shoots. There are 2 scripts of importance attached. The others have nothing to do with any of this.
First one deals with shooting and giving the bullet direction and speed. Here’s the part where I get my bullet:

GameObject bullet = projectilePool.GetPooledProjectile();
                bullet.transform.position = bulletStart.position;
                bullet.transform.rotation = Quaternion.Euler(bulletStart.eulerAngles.x, bulletStart.eulerAngles.y, angle + 270f);
                bullet.SetActive(true);
                bullet.GetComponent<BulletScript>().bulletTravelTime = bulletTravelTime;
                bullet.GetComponent<Rigidbody2D>().velocity = directionWithSpread;

The second script attached is the one with a simple object pooling I’ve made:

public GameObject projectilePrefab;
    List<GameObject> pooledProjectiles = new List<GameObject>();

    void Start()// Add 1 projectile in the pool at the start
    {
        GameObject projectile = Instantiate(projectilePrefab);
        pooledProjectiles.Add(projectile);
        projectile.SetActive(false);
    }

    //Method to get projectiles from
    public GameObject GetPooledProjectile()
    {
        //Check if there are any available projectiles
        foreach (GameObject projectile in pooledProjectiles)
        {
            if (!projectile.activeInHierarchy)
            {
                return projectile;
            }
        }
        // Create a new projectile if there aren't any
        GameObject newProjectile = Instantiate(projectilePrefab);
        pooledProjectiles.Add(newProjectile);
        return newProjectile;
    }

As for the bullet it only has a Sprite Renderer, Box collider switched to trigger, a RigidBody2D and this BulletScript which currently only has these 3 lines:

void OnEnable() { Invoke("DisableProjectile", bulletTravelTime); }
    void OnDisable() { CancelInvoke(); }
    void DisableProjectile() { gameObject.SetActive(false); }

When the player spawns in my game scene. A few block away there’s a gun on the ground. I’ll go pick it up.
At that point I Instantiate a gun on my player. Which enables the object pooling and shooting scripts on the gun. I’ve checked and there is a bullet clone instantiated in the editors hierarchy. It is set inactive. All as planned. But when I press left mouse button nothing happens. The bullet stays inactive. Only on the consecutive button presses it starts shooting properly.

Since I’ve only made the pool size 1. It is reusing the same bullet over and over again. But if I start clicking faster and I need another bullet to be added to the pool. The same thing happens. It does not show. I had a theory that the bullet needs some time to initialize or something before I can use it. In an Active state.
So I’ve changed to code a bit and right after adding it to the pool I’ve waited 0.1 seconds before I’ve set it inactive. Unfortunately it didn’t help. The first bullet still didn’t show.

Also when I’m reusing bullets. It seems that sometimes I see the bullet whooshing by from it’s last position to the guns bullet start transform. Instead of teleporting. I’ve tried to execute it in Update or in FixedUpdate. It didn’t help. I thought setting transform.position was a teleportation move and not a super fast moving technique :smile:

Anyone has any ideas please?

Execute a Debug.Break() wherever you fire that… it will pause the editor.

Does the code even run?

Is the bullet there in the scene?

Is it somewhere else?

Is part of it turned off?

This is all just standard old debugging 101, with the Unity “peer into the scene” twist.

By debugging you can find out exactly what your program is doing so you can fix it.

Use the above techniques to get the information you need in order to reason about what the problem is.

You can also use Debug.Log() to find out if any of your code is even running. Don’t assume it is.

Once you understand what the problem is, you may begin to reason about a solution to the problem.

ALSO:

The costs and issues associated with object pooling / pools:

In very rare extremely-high-count object circumstances I have seen small benefits from pooling.

In MOST circumstances, object pooling is a source of complexity, bugs and edge cases while not giving any measurable benefit.

I have went through some debugging before I’ve posted. Even tried asking chatgpt to help troubleshoot.
I’ve also tried the Debug.Logs. I’ve set a bunch of them in front of it and right after it as well. One was right after I set the bullet active and it still fired with no visible bullet on the scene. I didn’t know there was a Debug.Break() option I’ll try that.

But According to your post object pooling isn’t required for me. I guess I’ll just go back to instantiating things again.
Well at least I’ve learned some new things.

Thanks

Update:
I’ve tried the Debug.Break(). Added it right after I set it active. And checked the bullet it was inactive. Then I thought maybe the invoke is the issue. When I instantiate the bullet it is active so it might just set off that invoke. Fixed the code to do it in a different way. Didn’t help.

I’ve also took a closer look on the bullet after the Debug.break. When I activated it manually in the inspector. The bullet was in the correct position and a correct rotation. So the only issue is that it’s not active.

So I’ve tried to set it active multiple times in a row. Well that was pointless :smile:

At least I’ve figure out my other issue. The whooshing was caused by the bullet trail I’ve added to the bullet. Normally it’s barely visible so I keep forgetting it’s there.

Just in case you’re not aware (because it’s not really pointed out by them) Unity provides an object pooling system.

https://docs.unity3d.com/ScriptReference/Pool.ObjectPool_1.html

Good lord, where did I write that?! It is clear you didn’t read properly.

If you need pooling, you need pooling. If you don’t, you’re just wrecking your project.

1 Like

Well this was from your other posts:
Seriously, trust me, pooling objects can get really really complicated unless you are very disciplined about what objects get recycled and what state they have.

You will need to maintain and debug and grow that reset code for EVERY different flavor of thing in play now, plus EVERY NEW THING forever into the future if it is on a pooled object.

And in the end… oh look, it isn’t even any faster anyway because Unity3D is already a beast of an engine!

For 99% of games, object pooling is unlikely to make a visible performance difference.

Object pooling can also have a high cost as far as restructuring the lifetime of objects within your game.

I guess for a few bullets here and there I won’t be making my life harder. So it is not required for me. It’s not like I’m going to make the biggest bullet hell out there.

Why on earth are you doing this:

    void Start()// Add 1 projectile in the pool at the start
    {
        GameObject projectile = Instantiate(projectilePrefab);
        pooledProjectiles.Add(projectile);
        projectile.SetActive(false);
    }

This seems completely unnecessary. GetPooledProjectile already handles the case when there are no pooled projectiles available and creates one. I would guess this Start function is the source of your problem. Just delete it.

Well. When I was googling object pooling. I’ve seen people have some premade objects in the pool from the start. But at that time they had more of them premade so I’ve changed it. They had a for cycle there to add more of them. I’ve removed the for cycle and just added 1. Which is quite enough for weapons with slow fire rate. And I wanted to make it require the least memory as I could. It’s true that it’s quite useless now that I think about it. But the same issue arises when I’m adding another one into the pool. So simply removing this wouldn’t help.

Also I’ve already deleted everything related to object pooling and replaced that with the standard instantiate/ destroy method. I’m not going to rewrite the code anymore.

The bullet is showing up properly now.

Don’t reinvent the pool! :wink:

Unity has it built-in: Unity - Scripting API: ObjectPool<T0>
Store has a free asset that neatly wraps this API: https://assetstore.unity.com/packages/tools/utilities/master-object-pooler-2-146525

1 Like