# Why is my projectile not moving?

I am working on a simple 2D space shooter, and for whatever reason, my laser is not moving as intended when I press the fire button; it just sits there at the position it spawns at. I think my code should work, but obviously I am overlooking something. I have the gravity turned off and the mass is set quite low, so these speed numbers should be more than adequate. Any suggestions/insights are appreciated!

``````void ShootLaser()
{
overheatPercentage += 4;
++numShots;

if (numShots % 3 == 0)
{
GameObject tempObj = Instantiate(tracerShot, fireSpawn.position,fireSpawn.rotation);
Laser tracer = tempObj.GetComponent<Laser>();
tempObj.GetComponent<Rigidbody2D>().AddForce(fireSpawn.forward.normalized * 100, ForceMode2D.Impulse);
StartCoroutine(LaserShootCooldown());
}
else
{
GameObject tempObj = Instantiate(tracerShot, fireSpawn.position, fireSpawn.rotation);
Laser baseRound = tempObj.GetComponent<Laser>();
tempObj.GetComponent<Rigidbody2D>().AddForce(fireSpawn.forward.normalized * 60, ForceMode2D.Impulse);
StartCoroutine(LaserShootCooldown());
}

if(overheatPercentage >= 100)
{
StartCoroutine(Overheat());
}
}
``````

If this is 2D then why are you trying to add an impulse along the Z axis (Transform.forward)? Was this copied from a 3D reference? Rigidbody2D can only move in the XY plane and passing in a Vector3 to a method (AddForce) that only accepts a Vector2 means itâ€™ll strip the Z anyway.

If you want to add a force relative to the Rigidbody2D Z rotation then use AddRelativeForce. Beyodn that, if you just know the velocity you want then simply assign the velocity, no need to use a force/impulse.

Also, Iâ€™m wondering why youâ€™ve changed the mass; projectiles are typically Kinematic anyway so you can just assign the velocity and go. If youâ€™re doing this so it doesnâ€™t push the thing it contacts then consider using ForceSendLayers and ForceReceiveLayers to control this.

It was copied from my 3D project, yes. I am trying to get the laser to shoot in the positive Y it looks like, however if I try to use the .up property, it uses world space rather than local space, even when using AddRelativeForce(). Do you know what my next steps should be, troubleshooting-wise?

Thanks,
Austin

`````` void ShootLaser()
{
overheatPercentage += 4;
++numShots;

if (numShots % 3 == 0)
{
GameObject tempObj = Instantiate(tracerShot, fireSpawn.position,fireSpawn.rotation);
Laser tracer = tempObj.GetComponent<Laser>();
tempObj.GetComponent<Rigidbody2D>().AddRelativeForce(fireSpawn.up.normalized * tracer.speed, ForceMode2D.Impulse);
StartCoroutine(LaserShootCooldown());
}
else
{
GameObject tempObj = Instantiate(tracerShot, fireSpawn.position, fireSpawn.rotation);
Laser baseRound = tempObj.GetComponent<Laser>();
tempObj.GetComponent<Rigidbody2D>().AddRelativeForce(fireSpawn.up.normalized * baseRound.speed, ForceMode2D.Impulse);
StartCoroutine(LaserShootCooldown());
}

if(overheatPercentage >= 100)
{
StartCoroutine(Overheat());
}
}
``````

AddRelativeForce doesnâ€™t use world-space at all, it does what I said above. You need to therefore specify a local-space vector which â€śTransform.upâ€ť isnâ€™t.

Stop using transform references and use the correct Vector2 references i.e. Vector2.up in this case.

I have no idea what â€śfireSpawn.rotationâ€ť is but the only thing that matter is Z rotation which is the only degree of rotational freedom it has. You can see the rotation of the body in the inspector in the Info panel of the Rigidbody2D.

Hereâ€™s my super-simple treatment of the problem space: you can use it to add 2D shooting to just about anything you can imagine.

See the `SpaceShip2D` scene for it fully set up and operational, with a spaceship you can fly.

Man, I appreciate you trying to help, but your tone is awfully aggressive to a beginner

Donâ€™t read emotion into posted technical information. It wonâ€™t be helpful to you in any way, I promise you. In fact, it will hold you back, waste your time typing unnecessary text, and also make other unwilling to assist you, so donâ€™t do that to yourself. Itâ€™s not fair to you.

What Mel summarized for you is just what is already in the documentation, which apparently you missed reading. If you are using the physics API, use it correctly. Manipulating the Transform completely and utterly bypasses the physics API becauseâ€¦ itâ€™s NOT the physics API!!

In summary:

With Physics (or Physics2D), never manipulate the Transform directly. If you manipulate the Transform directly, you are bypassing the physics system and you can reasonably expect glitching and missed collisions and other physics mayhem.

This means you may not change transform.position, transform.rotation, you may not call transform.Translate(), transform.Rotate() or other such methods, and also transform.localScale is off limits. You also cannot set rigidbody.position or rigidbody.rotation directly. These ALL bypass physics.

Always use the .MovePosition() and .MoveRotation() methods on the Rigidbody (or Rigidbody2D) instance in order to move or rotate things. Doing this keeps the physics system informed about what is going on.

With a wheel collider, use the motor or brake torque to effect motion.

1 Like

Your code worked perfectly minus a slight rotation issue with my projectile, which is easy to fix. Appreciate your help!

I appreciate the info and general advice! Thanks a million!

I am sorry if I was oversensitive. Just a beginner trying to learn. Namaste

No problem, I wish you all the best, want you to focus on the fun stuff like learning the awesome Unity3D engine and making fun interactive experiences.

I suggest throwing yourself at EVERY type of simple game, just going nuts and working through tutorials, even by spending a little bit of time every day, and slowly you will build up confidence and linkages in your brain to understand how all of this works. Use the documentationâ€¦ it is there for your benefit and can really save you a lot of time.

Watch how this guy steadily layered on more and more knowledge:

Imphenzia: How Did I Learn To Make Games: