1
\$\begingroup\$

I am trying to develop something in Godot and I was hoping it would be possible to create some sort of gravity field. I do not mean just the default falling down indefinitely. I mean like a kind of field that pulls objects inside. Like planet Earth, no matter which side you are on our spheroid, you are pulled down towards the center.

I want something along these lines too. I want to have a specific area that attracts other nodes to it.

Let me illustrate. The black square is the entire world (2D sketch, but I want it in 3D) and the border square is the force field, with A and B being RigidBody nodes. Bodies and force fields

Node A is outside of the force field, so it should get pulled inside. Node B is already inside, it should not have any force attracting it further down the center.

Is this easily possible or would this require too complicated a setup?

\$\endgroup\$

3 Answers 3

1
\$\begingroup\$

I think the behaviour you're looking for is built into Godot with area.gravity_space_override = SPACE_OVERRIDE_REPLACE to change gravity when within a box and area.gravity_point = true to have a gravity well.

  1. Make two Area3D: the inner and outer boxes in your diagram.
  2. Set both to SPACE_OVERRIDE_REPLACE so the outer and set the outer one to lower priority so its gravity is ignored for objects inside the inner area.
  3. Set outer area's gravity to a point inside the inner area.

No script required: this can all be configured in the inspector.

\$\endgroup\$
0
\$\begingroup\$

You can achieve this effect in a few lines.

First we start by checking if the object is inside the area or not. Use the area_entered and area_exited signals from the Area3D class for this. Then if the object is outside of the area we apply a force towards the center of the area.

Putting this together should look something like this in GDScript, might need minor tweaks.

# In the gravity area script
var FORCE_STRENGTH = 100 # or however strong you want it 

var objects: Array[RigidBody3D] = []

func _process(delta: float):
    for object in objects:
        var direction = (position - object.position).normalized()
        object.apply_central_force(direction * FORCE_STRENGTH)

# Remember to connect these signals
func _on_enter(body):
    if body is RigidBody3D:
        objects.append(body)

func _on_exit(body):
    objects.erase(body)
\$\endgroup\$
1
  • \$\begingroup\$ Thanks! Guess I'll have to learn about Area3D first \$\endgroup\$ Commented Oct 11 at 18:40
0
\$\begingroup\$

If you want a Newtonian one sided gravity simplified equation:

A = f/R2 Where A is a scalar acceleration factor and R2=(P1.X-P2.X) * (P1.X-P2.X) + (P1.Y-P2.Y) * (P1.Y-P2.Y) + (P1.Z-P2.Z) * (P1.Z-P2.Z), the distance squared, and f is a "fudge factor" initially set to 1 and adjust as needed.

P1(A) and P2(B) are the center points of the objects.

You can apply the accelerations inside of an area3D by multiplying A by the direction vector (Sign(P2.X - P1.X),Sign(P2.Y - P1.Y),Sign(P2.Z - P1.Z)) and adding the result to the rigidbody velocity vector for every step while the object is in the area3D.


The R squared value in the denominator, while realistic in nature, tends to be a bit underwhelming, until it is not(values < 1). For many games, f is a function(sometimes piece-wise) of the distance, to make it "feel better".

\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .