- Home /
Fully understanding the gravity of the situation
I'm working on a 2D game where the player is technically a planet, and therefore their gravity affects certain objects in the game by pulling them towards the player if they come near them. So far everything is working and my prototype is going well, I just have one (possibly dumb) question. First of all I'm using this script from the script wiki to give the player gravity:
var range : float = 30.0;
function FixedUpdate () { var cols : Collider[] = Physics.OverlapSphere(transform.position, range); var rbs : Array = new Array(); for (c=0;c<cols.length;c++) { if (cols[c].attachedRigidbody && cols[c].attachedRigidbody != rigidbody) { var breaking :boolean = false; for (r=0;r<rbs.length;r++) { if (cols[c].attachedRigidbody == rbs[r]) { breaking=true; break; } } if (breaking) continue; rbs.Add(cols[c].attachedRigidbody); var offset : Vector3 = (transform.position - cols[c].transform.position); var mag: float = offset.magnitude; cols[c].attachedRigidbody.AddForce(offset/mag/mag * rigidbody.mass); } }
}
This works how I want it to, allowing me to attract all rigidbodies. My question is, and I apologize in advance because coding is not my strong point, is there a way to change this code so the affect of gravity would be greater when the player pressed a certain key?
For example, let's say right now if I'm within 30 m of an object it will come towards me at 1 m/s, but if I hit the space bar I would make it come towards me at 5 m/s?
As always any help is greatly appreciated.
Answer by skovacs1 · Oct 05, 2010 at 04:53 PM
Yes. That's quite simple.
To do something on key-press, you would use something like
if(Input.GetKey("Fire")) { //true every frame the key is held down //Do something }
if(Input.GetKeyDown("Fire")) { //true the frame the key is released //Do something }
if(Input.GetKeyUp("Fire")) { //true the frame the key is released //Do something }
Your gravity script is using a modification of simple Newtonian physics with the formula of mass / distance in the direction of the body. This is a rate of acceleration as it will increase as the distance decreases. To change the speed by which an object is attracted in the above script, you could change the mass, but bear in mind that this is an acceleration increase and will increase all subsequent speeds as well as the object gets closer(Other modifications made here to simplify the script)
var range : float = 30.0; var newMass : float = 2.0; private var oldMass : float = rigidbody.mass;
function FixedUpdate () { //If the key was pushed, change the mass if(Input.GetKeyDown("Fire")) { oldMass = rigidbody.mass; rigidbody.mass = newMass; } //If the key was released, change the mass back if(Input.GetKeyDown("Fire")) rigidBody.mass = oldMass;
var cols : Collider[] = Physics.OverlapSphere(transform.position, range); var rbs : Array = new Array(); for (c=0;c<cols.length;c++) { //Go through each collider in the area if (cols[c].attachedRigidbody && cols[c].attachedRigidbody != rigidbody) { var breaking :boolean = false; for (r=0;r<rbs.length;r++) { //Check if this one's been done if (cols[c].attachedRigidbody == rbs[r]) { breaking=true; break; } } if (breaking) continue; //Ignore it if it's been done rbs.Add(cols[c].attachedRigidbody); var offset : Vector3 = transform.position - cols[c].transform.position; cols[c].attachedRigidbody.AddForce(rigidbody.mass * offset/offset.sqrMagnitude); } } }
Note that both down and up are included here, rather than doing an if(...){...} else if(...){...}
. This was intentional. It is possible that someone both pressed and released within the time of one frame. An alternative would be something like
var range : float = 30.0; var factor : float = 2.0;
function FixedUpdate () { var cols : Collider[] = Physics.OverlapSphere(transform.position, range); var rbs : Array = new Array(); for (c=0;c<cols.length;c++) { //Go through each collider in the area if (cols[c].attachedRigidbody && cols[c].attachedRigidbody != rigidbody) { var breaking :boolean = false; for (r=0;r<rbs.length;r++) { //Check if this one's been done if (cols[c].attachedRigidbody == rbs[r]) { breaking=true; break; } } if (breaking) continue; //Ignore it if it's been done rbs.Add(cols[c].attachedRigidbody); var offset : Vector3 = transform.position - cols[c].transform.position; if(Input.GetKeyDown("Fire")) cols[c].attachedRigidbody.AddForce(factor rigidbody.mass offset/offset.sqrMagnitude); else cols[c].attachedRigidbody.AddForce(rigidbody.mass * offset/offset.sqrMagnitude); } } }
Thank you, I had just figured out that changing the mass would work and was co$$anonymous$$g to post the code I wrote to do that, but yours is much better and more thorough. Greatly appreciated.
Answer by Jesse Anders · Oct 05, 2010 at 04:51 PM
I don't know if this is what you're looking for, but in this line of code:
cols[c].attachedRigidbody.AddForce(offset/mag/mag * rigidbody.mass);
The force vector is:
offset/mag/mag * rigidbody.mass
If you add an additional multiplier to this expression, e.g.:
offset/mag/mag * rigidbody.mass * forceScale
The magnitude of the force will be scaled accordingly.
This won't necessarily change the rate of acceleration from one fixed value to another though. If you want the objects to move at fixed speeds that you can specify exactly, you may want to use some other method. (Among other things, the magnitude of the force in the above example is dependent on the distance between the two objects, so it's most likely going to change over time.)