+2 votes

Hello, I am suffering for the second day. There is a large cube made up of smaller cubes that can be destroyed. How to make gravity on this cube? So that you can walk on either side and jump over to the other side? help me please

in Engine by (17 points)

1 Answer

0 votes
Best answer

I've tried in a basic project and it seems to work so you could use an Area with a rectangle collision shape. This will represent the space where there's gravity.

Under the area you set the space_override property to something else that disabled. (See the values https://docs.godotengine.org/fr/stable/classes/class_area.html#enumerations).
You should also set gravity_point to true and gravity_vec to Vector3(0, 0, 0)

EDIT: For completeness. If you want to use a gravity_vector and modify it at runtime, as of Godot 3.3 rc6 it still doesn't work with Bullet so you should use Godot physics instead.

Under Project Settings > General > Physics > 3D > Physics Engine choose GodotPhysics.

by (621 points)
edited by

I tried this, and unfortunately, this is not what I need. The body will not be able to move freely along the face of the cube, the body will tend to the center of the face (side). I have attached a picture of how it will look, I have already tried it. And I need the body to move freely on either side of the cube, as if moving on a plane. This can be done?
https://ibb.co/1KnKh5w - gravity point

Yeah you're right! I think you need to do something yourself there. You could keep track of the face on which the player need, and apply gravity opposing the floor normal. You manually check the gravity each time the player switch face.

PhysicsServer.area_set_param(
    get_world().get_space(), 
    PhysicsServer.AREA_PARAM_GRAVITY_VECTOR, 
    Vector3(0,1,0)
)

See https://docs.godotengine.org/en/3.1/classes/class_physicsserver.html

but how to track the side of the cube that is needed?

You could put an Area covering the whole floor, or the whole space for each face. When your player is entering the area you get a signal, and change the gravity accordingly.

thanks, I almost succeeded. I put SPACIAL in the center of each face and gave them different names (UP, DOWN, FORWARD, and so on). In the process_delta function, I measure the distance from the body to each SPATIAL and write everything into an array (there are 6 cells in it because there are 6 faces). For example, 1 cell stores the distance from the body to SPATIAL UP and so on. Then I search for what index in the array the minimum distance from the body to each SPATIAL is stored. And so I can find out on which side of the cube the body is now. But I got a problem: I cannot change the global gravity settings in the _process (delta) function, it only works in _ready.
How do I change the global gravity settings every frame or second??

PhysicsServer.areasetparam(getviewport().findworld().getspace(), PhysicsServer.AREAPARAMGRAVITYVECTOR, Vector3(0,0,-1))

Good to know you're finding a solution!

I have a project where I change the gravity in 2D in the _process() function and it works. How do you know it's not working, do you get an error message?

In case it's not working as you want, you could go back to the setup with the Area, you put gravity_point to false and set gravity_vector to want you want.

yes it is really easier. Thank you very much for helping. But why isn't this piece of code working?)

if(num == 0):
    gravityArea.gravity_vec(0,-1,0)
if(num == 1):
    gravityArea.gravity_vec(0,0,-1)

Error: Invalid call. Nonexistent function 'gravity_vec' in base 'Area'.

The error is telling you what's happening. You're trying to use gravity_vec as if it were a function, but it's a property. https://docs.godotengine.org/fr/stable/classes/class_area.html#class-area-property-gravity-vec

You should use it like so:

gravityArea.gravity_vec = Vector3(0,-1,0)

or by using the setter function

gravityArea.set_gravity_vector(Vector3(0,-1,0))

Forgive me for so many questions, I'm already ashamed to ask. Why does gravityArea.gravity_vec = Vector3 (0,0,1) only work in the _ready function? Neither in physics_process (delta) nor in process (delta) gravity change does not work.

func _ready():
gravityArea.gravity_vec = Vector3(0,0,1)

everything works

func _physics_process(delta):
if Input.is_action_just_pressed("num1"):
    gravityArea.gravity_vec = Vector3(0,-1,0)
    print(gravityArea.gravity_vec)

if Input.is_action_just_pressed("num2"):
    gravityArea.gravity_vec = Vector3(0,0,1)
    print(gravityArea.gravity_vec)

does not work, although it is written in the console output that the vectors are changing

I've tried on my side and you're right it doesn't work if you try to change the vector at runtime. I now remember, I've found a bug in Bullet physics, you should use Godot physics instead.

Under Project Settings > General > Physics > 3D > Physics Engine choose GodotPhysics. It should work now! I just tested it in a small project.

it works, but somehow bad. Can you please give your test project?

Here: https://transferxl.com/08vH9RHMMjxc60

If you run the scene and press space, it will toggle between Vector3(0, -1, 0) and Vector3(0, 1, 0)

Thanks, I figured it out, now everything works. The last question: why can't other bodies interact with this body? For example, I have a kinematic body character, if I touch my ball, the character will jump onto the ball and will not be able to move. Why?

Welcome to Godot Engine Q&A, where you can ask questions and receive answers from other members of the community.

Please make sure to read How to use this Q&A? before posting your first questions.
Social login is currently unavailable. If you've previously logged in with a Facebook or GitHub account, use the I forgot my password link in the login box to set a password for your account. If you still can't access your account, send an email to webmaster@godotengine.org with your username.