Direction of AddForce Not Consistent

I’m applying a force to fire a projectile, but the direction of the projectile is not always constant. The direction of the force is the forward direction of the gun’s muzzle:

pObj.GetComponent().AddForce(muzzleObj.transform.forward * 150f, ForceMode.Impulse);

I’ve used this code for projectiles before, and it always worked as expected. But even when the gun direction is constant, the direction of the projectile seems to be random. It won’t let me attach a video, so below are 3 screen captures showing three different directions of the projectile when the gun is facing the same direction. The direction of the force (muzzleObj.transform.forward) has the correct (same) value. I’ve gotten ridden of the projectile’s particle effects and all attached scripts. The projectiles in the screen captures are just spheres with colliders and rigid bodies attached. Also, it doesn’t make any difference where I launch the projectiles from, e.g. above or to the side of the muzzle, or even from a fixed position away from everything. There are no colliders anywhere near the projectiles, so they are not being deflected by a collision.

This only happens when the gun is NOT at zero rotation. When the app first starts, if I fire from the starting rotation, Vector3.zero, the projectiles always fire straight. It’s only after moving/rotating away from zero that the projectiles fire in random directions. Any ideas what might be causing this?

Does the muzzle have a collider?. It’s a very common bug where projectiles are instantiated overlapping the gun’s collider and this causes the projectile to go off in unexpected directions.

No, there is no collider on the gun or muzzle. Just to be sure, I tried firing the projectile from various other locations away from the gun, same result, random directions if the gun is not rotated to zero. I also attached a script to the projectile with a collision handler, and it’s not being triggered by a collision.

Have you debugged the actual direction? Such as using Gizmos or Debug.DrawRay to ensure the direction you’re using is correct? Maybe you’re using the wrong transform? You’re stringing a bunch of method calls together so you should really space it out to allow you to properly debug it.

I haven’t ever noticed any issue with AddForce, so I think it’s unlikely the problem is in AddForce itself. I’d try a couple of things to debug the issue and figure out the cause:

  • Use a constant unit vector instead of transform.forward.
  • Ensure AddForce is called from FixedUpdate. If it’s being called from Update (or any other method), then transform.forward might vary between physics frames.
  • How the projectile is instanced, and in which Unity event/method? If the projectile is affected by gravity, then it might happen that one physics frame passes between the projectile is instanced and the moment you apply the force. This initial simulation step might cause different results each time. For better Physics consistency, everything related to physics (including instanding rigidbodies) should happen within the FixedUpdate cycle.

Yes, the actual direction, transform.forward, is the same every time. So even if it’s the wrong direction, or wrong transform, the projectile should still go in the same direction. Nothing is changing, I’m just rotating the gun once, then clicking the fire button repeatedly.

I’m not stringing a bunch of calls together. When the fire button is clicked, the projectile is instantiated, and then a force is applied to it. The projectile has a non-kinematic rigidbody and collider attached.

• When I use a constant vector, e.g., Vector3.zero, the projectile always fires in the same direction regardless of gun rotation, as it should.
• Force is applied in the function called when the Fire button is clicked, not in an Update or FixedUpdate method. This problem occurs when the gun is stationary, not moving or rotating between frames. This same code has worked just fine for me in other apps.
• In the function that’s called when the Fire button is clicked, the projectile is instantiated (from a pool), its parent & position is set, then the force is applied. The projectile is non kinematic and does not use gravity. Its Y position is frozen.
• When I draw a ray, the ray is correctly aligned with the gun, so the direction (muzzleObj.transform.forward) is correct. So it must be something going on with the projectile.

When instantiating Rigidbody objects from a pool, be sure to set their velocity and angularVelocity to zero at the time of instantiation (or the time of deactivation). You are probably fighting the last frame of velocity at the end of that bullet’s previous awake lifetime.

3 Likes

As above, I came here to say that you should simply be setting the velocity and not adding an impulse, especially if you’re reusing in a pool.

It’s the collider attached to the projectile that’s causing the problem. If I disable the projectile’s collider or make it a trigger, the projectile fires correctly. It doesn’t make a difference if the collider is a sphere or a box. But this script, attached to the projectile, does not register a collision:

    public void OnCollisionEnter(Collision col) {
        print(col.transform.name);
    }

This code is working correctly, as it is called when the projectile hits a wall.

So, how can the collider be causing the change in direction if it’s not colliding with anything?

Yes, that’s it. In the project I took this code from, I was not using a pool.

Thanks to everyone!

It won’t affect the linear velocity of the Rigidbody. It won’t perform that callback if it’s a trigger.

Total guesswork here on what you’re doing for instantiating etc.