- Home /
Planetary gravity for not so round object?
I tried to use the FauxGravity scripts ,but they only work on perfectly spherical planets. I am trying to override the unity 3d built in physics to create physics for the player to stand on an object like a planetoid. It is not perfectly circular so the script doesn't work. Does anybody have any scripts or tips on how I could get a good gravity system like that to work?
I could just create my own movement functions in the script that controls the gravity to create a whole new physics and movement system. What do you think. It would be easier to make the walking forward and everything.
Answer by Clet_ · May 21, 2014 at 04:15 AM
Assuming you don't have corners on that not-so-round object, the way to achieve that would be by applying the gravity in the opposite direction of the normal of the surface you're walking on.
You'd have to store the normal every frame, to adapt to the planet's curve and then, raycast in that direction, updating the normal and apply gravity in the opposite direction of that new normal
private Vector3 _lastNormal = Vector3.up; //This line assumes you're first frame normal is looking upward
private Vector3 _velocity;
public float gravity;
private void FixedUpdate () {
RaycastHit hit;
if(Physics.Raycast (transform.position, -_lastNoraml, out hit, 10f, ~(1 << LayerMask.NameToLayer ("MyPlanetLayer"))) {
_lastNormal = hit.normal;
}
_velocity += gravity * -_lastNormal * Time.deltaTime;
_transform.position += _velocity * Time.deltaTime;
}
I didn't test this code, but the idea of it is relatively obvious. Your turn to adapt it
mightysprite comment on $$anonymous$$ileSplit's answer invalidated this method. Please disregard
Could I switch out the layer with the gameobject of the planet ins$$anonymous$$d?
The layer is simply there to avoid to raycast against every gameObject with a collider in your scene.
If you put your planet on the "$$anonymous$$yPlaneLayer", it will be a quicker raycast than a raycast against every kind of collider and then checking iof it's the planet.
The ~ is the binary NOT. Each number are written in binary, and this operator just changes every 1's into 0's and vice-versa. The line
~(1 << Layer$$anonymous$$ask.NameToLayer("$$anonymous$$yPlanetLayer"))
is there to make sure the collision test is made ONLY on the $$anonymous$$yPlanetLayer. Layer$$anonymous$$ask script reference
Since the answer to which I made a comment seems to have disappeared (and @Clet_ referenced it above), I suspect that my comment generally said that you may not find this method working quite like you expect. Since you'll always jump and fall perpendicular to the surface, when you're on a "hill" you'll jump also perpendicular to that surface. The steeper the hill from the "expected horizontal plane," the more awkward it will feel. What you could do though is some weighted blend between the normal of the polygon you're on and the direction from the center of mass to the player, this might feel ok but you'll have to play with it to see.