I am trying to fire projectiles from a player who is moving at very high speeds. The issue is that the bullets do not seem to inherit the angular velocity. If the player is moving in a straight line at 500 U/s, then the bullet correctly inherits that velocity and adds its own speed onto that:

GameObject bullet = Instantiate(projectile, gun.transform.position, gun.transform.rotation);
bullet.GetComponent<Rigidbody>().velocity = r.velocity + bullet.transform.forward *bulletSpeed;

However, if the player is turning really quickly, it does not inherit the rotational velocity, and the bullet looks like it veers off to the side.

How can I implement this? I tried assigning the angular velocity of the player to the bullet, but this just caused the bullet to spin while moving in the same direction.

Some extra details:

  • I am using rigidbody.MoveRotation() to rotate my player, but I manually calculated angularVelocity to assign it to the bullet

  • I tried moving the player with AddTorque(), but could not produce any results with the bullets


We can slightly improve the perceived course of the projectile by taking the velocity of the muzzle of the gun, rather than the velocity of the body's pivot. This will include any sideways linear velocity due to the gun swinging around at an offset from the body's center of mass as the body rotates:

// I'd recommend defining your prefab as Rigidbody type, so that you
// can get it directly from the Instantiate without a GetComponent call
Rigidbody projectile;

void Fire() {    
    Rigidbody bullet = Instantiate(

    // Inherit not just the linear velocity of the parent's center of mass,
    // but also the sideways motion due to the parent's angular velocity.
    Vector3 inheritedVelocity = r.GetPointVelocity(gun.transform.position);
    bullet.velocity = inheritedVelocity + bullet.transform.forward * bulletSpeed;    

To make this work, you'll need the body to have a valid angular velocity. Assuming you're setting the rotation each frame, you can adapt your existing MoveRotation code to use this instead:

void MoveRotationWithAngularVelocity(Quaternion rotation) {
    Quaternion delta = rotation * Quaternion.Inverse(r.rotation);

    float angle;  Vector3 axis;
    delta.ToAngleAxis(out angle, out axis);

    // I don't recall the range returned by ToAngleAxis, so this is just to be safe.
    if(Mathf.Abs(angle) > 180f) {
        axis = -axis;
        angle = 360f - Mathf.Abs(angle);

    // Compute an angular velocity that accomplishes this rotation in 1 time step.
    r.angularVelocity = angle * Mathf.Deg2Rad * axis / Time.deltaTime;

The difference between the normal MoveRotation and this one is that the object will keep spinning with inertia on subsequent updates, but if you're setting its rotation each FixedUpdate anyway then the angular velocity calculated will naturally go to zero once it arrives at the target rotation.

Note that this will not ensure that the bullet stays in line with the barrel as the barrel continues to rotate through a wide angle. That doesn't happen in real physics: think of a rock released from a spinning sling - the rock inherits the linear velocity of the end of the sling at the moment of release, and zips off in a straight line, not an expanding spiral revolving about the sling's pivot.

If you want to trace such a spiral instead of the normal straight-line trajectory that physics suggests, then you'll need a script on the bullet to apply additional compensating accelerations each frame. If that's what you need, comment and I'll add formulas for calculating those accelerations.

  • \$\begingroup\$ This is a great answer, thank you! I modified it a bit by adding force to the inherited velocity instead of modifying the velocity itself, but it seems to work for me! \$\endgroup\$
    – gkgkgkgk
    Aug 16 '18 at 17:22

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.