rigidbody2d.AddForceAtPosition Doesn't Add Horizontal Movement?

I have a simple rigidBody2D object in my scene. When I click on the screen I do a ray cast from the bottom of the screen to the top at the x-position of where my mouse click was. If the ray cast hits the rigidbody then the rigidBody does this:

rigidbody2D.AddForceAtPosition(Vector2.up * 100.0f, impactPoint);

Where impactPoint is the point where the ray cast hit the collider. What I want is this to act like a bullet was fired straight upwards, hitting the rigidBody and imparting velocity and angular velocity on it. So when the ray cast hits the far right edge of the collider I want the rigidbody to move upwards, to the left, and to spin counter-clockwise.

However the actual result of AddForceAtPosition is just that the object moves perfectly straight upwards and starts spinning around its center.

Why isn’t the rigidbody moving to the left or right? Is AddForceAtPosition not able to simulate being hit by a very small, very fast traveling object?

If you apply an upwards force, then the body will only move upwards. If you want it to move sideways you need to apply a sideways force as well. The “at position” bit doesn’t change this, it just make it add a torque as well.

In reality the end result of this kind of collision depends hugely on the bounce angle of the bullet, assuming it bounces off at all. It’s probably not worth you worrying about the maths though. You will probably get a good result if you calculate a normal vector from the bullet towards the target object, and apply an impulse to the target object in that direction, scaled by the dot product of the bullet’s incoming velocity with this direction vector.

This will apply the maximum impulse when the bullet his the target squarely from below, with a sideways component if it doesn’t hit it squarely, and the magnitude of the impulse will decay to zero as the bullet’s impact gets more tangential.

Something like this:

var direction = (target.position - bullet.position).normalized;
var magnitude = MaxImpulse * Vector3.Dot(direction, bullet.rigidbody.velocity.normalized);

then apply an impulse of direction*magnitude.