- Home /
How do I change force of gravity for a single object?
I've got an object that I want to fall at an acceleration of 3 G's. My current method of doing this is to turn gravity off for the object, and apply a downward force of 3*Physics.gravity each tick. Unfortunately, applying a force every tick prevents the rigidbody from ever sleeping.
My hope is to have a lot of these objects, have them fall, and once they reach a resting place, put the rigidbody to sleep. This all works as expected if I let the rigidbody use its built-in gravity, but then I can't modify the gravity force for individual objects.
Anybody know how to solve this?
Dear Azound, "Gs" is just a plural -- there is no apostrophe!
Perhaps you could hit "edit" and get rid of that apostrophe! Cheers
Answer by aldonaletto · Jan 20, 2012 at 10:40 PM
You can apply a force as you were already doing, but check rigidbody.velocity: when it's below a low value during some number of consecutive physics cycles, remove the force and let the rigidbody sleep like a log:
private var limit: float = 0.01;
private var cycles: int;
private var cyclesToSleep: int = 10;
function FixedUpdate () {
if (rigidbody.velocity.sqrMagnitude > limit){
cycles = cyclesToSleep; // reload counter if velocity isn't negligible
}
if (cycles > 0){ // while counter > 0 apply force
cycles--;
rigidbody.AddForce(3 * Physics.gravity);
}
}
If something hits and moves the rigidbody, the force is re-enabled.
I'm not doing the force application inside a behaviour - It's in a callback that has access to the gameObject, but doesn't have any place to store a cycles count. I could reengineer everything to work inside an object that has state, and I may have to if the ConstantForce technique doesn't work. It would be easy to check the velocity, but without watching it over time, you can't be sure whether it just reached the apex of a toss straight up, or settled on the ground.
I tried ConstantForce, but it didn't let the rigidbody sleep. $$anonymous$$aybe you could keep the original gravity and add the force only when the velocity isn't negligible: the extra gravity would be turned off when reaching an apex, but the original one would keep moving the rigidbody, turning the extra gravity on again quickly enough to avoid any noticeable glitch.
Aldonaletto's variation is the one I went with. ConstantForce does prevent sleeping, so I created my own behaviour and count cycles where velocity is low.
Obviously, you may want to change my Update function to FixedUpdate, but here's my class:
using UnityEngine;
[RequireComponent(typeof(Rigidbody))] class ApplyForce : $$anonymous$$onoBehaviour { public Vector3 force = Vector3.zero; public Vector3 torque = Vector3.zero;
/// <summary>
/// Causes the force to be applied in the gameObject's local space.
/// </summary>
public bool relative = false;
/// <summary>
/// Causes the force to ignore mass and accelerate at the given force rate.
/// </summary>
public bool accelerate = false;
public float sleepVelocity = 0.01f;
private int cycles = 0;
public void Update() {
if (rigidbody.velocity.sqr$$anonymous$$agnitude < sleepVelocity * sleepVelocity) {
++cycles;
}
else {
cycles = 0;
}
if (cycles > 3) {
Object.Destroy(this);
return;
}
Force$$anonymous$$ode mode = accelerate ? Force$$anonymous$$ode.Acceleration : Force$$anonymous$$ode.Force;
if (relative) {
rigidbody.AddRelativeForce(force, mode);
rigidbody.AddRelativeTorque(torque, mode);
}
else {
rigidbody.AddForce(force, mode);
rigidbody.AddTorque(torque, mode);
}
}
}
Answer by dannyskim · Jan 20, 2012 at 08:21 AM
You could turn gravity off and apply a constant force, and then turn that constant force off or manipulate the constant force to your specifications. You can add a constant force a rigidbody by going to component -> physics -> constant force. Or you can change the constant force by script if you wish:
http://unity3d.com/support/documentation/ScriptReference/ConstantForce.html
I forgot that ConstantForce was a built-in type. I'll give that a try tonight and see if it plays nicely with rigidbody sleeping :)
Answer by Kryptos · Jan 20, 2012 at 08:28 AM
You can try to apply by default a very strong gravity (3G's) but put a big drag on your rigidbodies to make them look as they were falling at only one G.
Then if you need an object to fall at 3G's, just put the drag to zero (or a very small value).
Or maybe mixing my solution with the one suggested by @dannyskim.
Ha! gotta love a good hack :) Hopefully the constant force technique works, but I'll keep this in $$anonymous$$d as a backup.
The drag suggestion is one I would have made as well....
Answer by Creator347 · Jul 02, 2013 at 06:58 AM
Physics.gravity = new Vector3(0, -1.0F, 0);
http://docs.unity3d.com/Documentation/ScriptReference/Physics-gravity.html