Bullet Momentum

Hi,

I have a spaceship with a launcher on it that fires a projectile. When I shoot, the bullet fires fine when staying still. When I move the spaceship and shoot, the bullet can not keep up with the speed of the ship. I need a way for the bullet to take the ship’s velocity into account in addition to its speed. How can I achieve this?

Here is what I have so far:

var projectile : Rigidbody;
var speed = 20.0;
var launcher : Rigidbody;

function Update()

{

	if(Input.GetButtonDown("Fire1"))
	{


                  var instantiatedProjectile : Rigidbody = Instantiate (projectile, transform.position,  GameObject.Find("rotationspawn").transform.rotation);
		
                  instantiatedProjectile.velocity = transform.TransformDirection (new Vector3(0, 0, speed));

	
	}
	
}

Add the ship’s velocity to the velocity you’re already assigning.

I know that as a concept, I just can’t figure out how to code it.

var projectile : Rigidbody;
var speed = 20.0;
var totalSpeed : float;
var launcher : Rigidbody;
var ship : Transform;

function Update()

{

        totalSpeed = ship.scriptName.varName + speed;

	if(Input.GetButtonDown("Fire1"))
	{


                  var instantiatedProjectile : Rigidbody = Instantiate (projectile, transform.position,  GameObject.Find("rotationspawn").transform.rotation);
		
                  instantiatedProjectile.velocity = transform.TransformDirection (new Vector3(0, 0, totalSpeed));

	
	}
	
}

I’m not sure how to implement that. How do I calculate the current velocity of the ship in the other script? Can it be in a single script?

I tried something like this:

var projectile : Rigidbody;
var speed = 20.0;
var totalSpeed : float;
var playerShip : Rigidbody;

function Update()

{

var playerSpeed = playerShip.rigidbody.velocity.magnitude*1;

totalSpeed = playerSpeed + speed;

	if(Input.GetButtonDown("Fire1"))
	{


                  var instantiatedProjectile : Rigidbody = Instantiate (projectile, transform.position,  GameObject.Find("rotationspawn").transform.rotation);
		
                  instantiatedProjectile.velocity = transform.TransformDirection (new Vector3(0, 0, totalSpeed));

	
	}
	
}

but its not acting any different from my initial code. Any help?

JM’s code is wrong, that’s not how you access variables across objects.

Somewhere you are controlling your ship’s movement. Either by applying force to it or by directly moving it via transform.position or .Translate.

If you’re using force, you can use:

var shipObject : Rigidbody; // set in inspector
instantiatedProjectile.velocity += shipObject.velocity;

If you’re ‘teleporting’ your ship by setting its position directly, then you need to be storing its movement somewhere. For instance you might have in “Ship.js”: (name’s not important)

var speed : Vector3;
function Update() {
  transform.position += speed * TIme.deltaTime;
}

In that case you’d use:

var shipObject : Ship; // or whatever your ship script is named - set in inspector
instantiatedProjectile.velocity += shipObject.speed;

HOWEVER

It’s best for your firing code to go in the same script as the rest of your input - spreading input out over multiple scripts can only cause headaches later. Plus, your ship should know about its weaponry; there’s little logical disconnect between them (if any). And if the two scripts are combined then it’s trivial to get the ship’s movement velocity added to its weapons-fire velocity.

Vicenti, thank you for all the help, but I am still having problems.

I created a new script called Ship and entered your code in it

var speed : Vector3;
function Update() {
  transform.position += speed * TIme.deltaTime;
}

I then attached this script to my ship object. I then entered the following code into my launcher script.

var shipObject : Ship; 
instantiatedProjectile.velocity += shipObject.speed;

I then referenced the ship object in the inspector. I try the game, but now my bullets don’t move anywhere and still don’t move at the same velocity as the ship. Any idea whats wrong?

Try this:

var rotationspawn : Transform;

		var forward = transform.TransformDirection(Vector3.forward);
		var newBulletSpeed = speed + shipObject.transform.rigidbody.velocity.magnitude * 5; //Modify this multiplier (*5) depending on the mass of your projectile

		var instantiatedProjectile : Rigidbody = Instantiate (projectile, rotationspawn, Quaternion.identity);

		instantiatedProjectile.rigidbody.AddRelativeForce(transform.forward * newBulletSpeed);
		instantiatedProjectile.transform.rotation = rotationspawn.transform.rotation;

I am getting the error:

No appropriate version of ‘UnityEngine.Object.Instantiate’ for the argument list ‘(UnityEngine.Rigidbody, UnityEngine.Transform, UnityEngine.Quaternion)’ was found.

for this line:

var instantiatedProjectile : Rigidbody = Instantiate (projectile, rotationspawn, Quaternion.identity);

Delete - : Rigidbody - and see what happens

I’m getting the same error

You need to use rotationspawn.position, not just rotationspawn. :slight_smile:

As for the problem with mine - are you using updating speed to be the ship’s speed? That’s kind of important. :slight_smile:

And if you get an error here:

		instantiatedProjectile.transform.rotation = rotationspawn.transform.rotation;

delete the .transform, rotationspawn is already declared as var : Transform.

		instantiatedProjectile.transform.rotation = rotationspawn.rotation;

Sorry about the errors, I can’t test this code in Unity at the moment.

Ok, changing it to rorationspawn.position removed the error, but the bullet still fires without any velocity, even with the ship moving.

As for the problem with mine - are you using updating speed to be the ship's speed? That's kind of important.

I have your code:

var speed : Vector3;
function Update() {
  transform.position += speed * Time.deltaTime;
}

in a script attached the ship and referenced from the launcher script. Is there anything else I need it to do to be updating the speed of the ship?

Sorry about the errors, I can't test this code in Unity at the moment.

Celinscak, I did not get any other errors.

Thanks everyone for the help

Can you post the entire new code? These segments are hard to compile in my head now :slight_smile:

No problem,

The code on the launcher object. (the launcher is a child of the ship)

var projectile : Rigidbody;
var launchSpeed = 20.0;
var rotationspawn : Transform;
var shipObject : Ship; 

function Update()
{
	if(Input.GetButtonDown("Fire1"))
	{

                var forward = transform.TransformDirection(Vector3.forward);
		var newBulletSpeed = launchSpeed + shipObject.transform.rigidbody.velocity.magnitude * 5; //Modify this multiplier (*5) depending on the mass of your projectile

		var instantiatedProjectile : Rigidbody = Instantiate (projectile, rotationspawn.position, Quaternion.identity);

		instantiatedProjectile.rigidbody.AddRelativeForce(transform.forward * newBulletSpeed);
		instantiatedProjectile.transform.rotation = rotationspawn.transform.rotation;	
	}
	
}

The code on the ship object:

var speed : Vector3;
function Update() {
  transform.position += speed * Time.deltaTime;
}

You’re moving your ship every frame directly using transform.position. Thus, the physics engine has no idea what it’s speed is, as far as it’s concerned it’s a stationary object that teleports every frame. So shipObject.transform.rigidbody.velocity.magnitude is probably 0. If you want to calculate the speed of the ship, you’ll need to store it’s position every frame, then use something like (transform.position - oldposition) / Time.deltaTime. You could then pass this value to the launcher so it can use that. If you’re going to go that route, you might as well just move the projectile the same way, using transform.position += speed * Time.deltaTime

If you want to move your ship via physics, then your code might almost work, but I’d recommend using ForceMode.VelocityChange to set the speed of the projectile directly instead or just applying a force.

This is the issue:

var shipObject : Ship;

it should be:

var shipObject : GameObject;

Then assign your shipObject to this script in the inspector and the thing should work.

EDIT: Try adding more speed, like 20000.

I’m having the same issue, only I’m making a first person shooter and using the FPS controller.

This is what I have going on right now:

The bullets spawn fine from the barrel of the gun when standing still, moving the mouse does not cause them too lag behind. But when I move around the bullets lag behind. I assume I need to get my velocity from the character motor script, but that script is massive and I can’t even find where the “push this button to move” code is. Can anyone tell me where I should start?

If you are using a CharacterController than you can get the velocity from that.

CharacterController controller;

//…

controller = GetComponent();
Vector3 velocity = controller.velocity;

//… etc

In real life the momentum of a person holding a gun would have such a small affect on the trajectory of the bullet that it would not be noticeable. Bullets travel pretty damned fast. Most games just use “speed of light” instantaneous bullets for machine guns and pistols, and they reserve the physics simulations for rockets and slower moving projectiles.