Propulsion based on Newton's third law

First off: I’m totally new to Unity and amazed by how mature and developer friendly this framework is. I’m late to the party, but plan to stay :slight_smile:

My question:

I’ve made a scene with a spaceship flying across terrain. The ship is subject to gravity, and the user applies degrees of force upwards at the down-facing side of the ship to keep it flying. This is fine, but what I really want to do, is have the ship fire lots of tiny objects (with mass) downwards, thus gaining upwards momentum as per Newton’s Third Law. How would I go about solving this? Are there any tutorials on the subject? Would such a propulsion system be feasible at all, performance-wise?

Also, is it possible to change the center of mass for an object? It would be cool if ship rotation could be changed during flight by shifting the spaceship center of mass.

I’m sure these are noob questions, and apologize in advance for my lack of knack. Very grateful for any tips at all on these subjects!

EDIT: I figured out how to set center of mass, so only my first question stands unanswered.

This may help GitHub - GamePhysics101/02-Newtons-Laws: Newtons laws of motion explained through Unity 3D in C# as part of https://www.udemy.com/gamephysics.

Welcome! Same happened to me 7 years ago, and I’m still here.

Sure, you can do that and it’s pretty straightforward.

First, a basic reminder you may have already figured out: ensure to do all your physics-related stuff in the FixedUpdate call. FixedUpdate is called at the constant rate of the physics (50Hz by default) without skipping any physics frame. Use Update for the visual stuff. Update is called at the visual frame rate (variable), and frames may get skipped if necessary.

I’d start defining the mass and velocity of each tiny object that gets fired. That makes an impuse itself (mass times velocity). Then you may simply apply that impulse to the main rigidbody with Rigidbody.AddForce in impulse mode, like this:

rigidbody.AddForce(transform.up * impulse, ForceMode.Impulse);

This will apply the ship an impulse in its local “up” direction. If you are firing, lets say, 1000 objects per second, then you may put the above in a loop:

int firedThisFrame = Mathf.RoundToInt(1000 * Time.deltaTime);
for (int i=0; i<firedThisFrame; i++)
    rigidbody.AddForce(transform.up * impulse, ForceMode.Impulse);

AddForce is somewhat “free”: all calls are accumulated in a resulting value, which will be applied to the rigidbody after the FixedUpdate call. You may also calculate the final impulse yourself and apply the result via a single AddForce call, instead of using a for loop:

int firedThisFrame = Mathf.RoundToInt(1000 * Time.deltaTime);
rigidbody.AddForce(transform.up * impulse * firedthisFrame, ForceMode.Impulse);

Also remember to subtract the accumulated mass of the “fired” objects from the rigidbody.

As the mass of the objects is tiny, you will have to fire them at a very large speed (in the order of 3000 - 7000 m/s for a realistic ship) and at a large number for making the impulse significant for your ship. Some basic rocket science will be useful here.

As for the tiny objects that are actually fired, personally I’d just configure a Particle System for them. This might be purely a visual effect, or you may even configure the particles to physically collide with other objects.

Otherwise, implementing that part would require you to implement an object instantiation / disposal manager. You would be responsible of creating each object, giving it a startup state, and dispose it at the end of its lifecycle. I think this is a different level of difficulty.

Keep creating! :slight_smile:

2 Likes