How to set a rigidbody2d position in 4.0

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By RBbooms

I am trying to make a catch the falling objects minigame for a project i’m working on, but I am having some issues. To optimize things, I made 4 different rigidbody2d’s which fall to the floor at different speeds, and report a collision once touching the ground, and reset at the top of the screen at a random x-value. So far I’ve tried changing just position to global_position, and moving the object after freezing it on a call_deferred, but every time it changes its position visually, but the collision still is in the same place, and after unfreezing it snaps back to its first position. If this is an _integrate_forces() issue please explain what I should do for the syntax, as this is my first time doing stuff with rigidbody2d’s. Here is an example of one of my body_entered functions just for reference.

if body == $Ground:
	lives -= 1
	if lives == 0:
if body == $Player:
	count += 1

$BallA2.call_deferred("set_freeze_enabled", true)
$BallA2.global_position = Vector2(randf_range(8,1144), 0)
await get_tree().create_timer(randf_range(3,7)).timeout
$BallA2.call_deferred("set_freeze_enabled", false)

Just to clarify, as I forgot to mention this: Once reporting that collision the ball is meant to freeze at the top of the screen for a small randomized amount of time before unfreezing and falling again. Thanks for any help, as both me and the discord I’m a part of are all stumped.

RBbooms | 2023-05-28 02:08

:bust_in_silhouette: Reply From: rhennig

Something like this should work.

func _on_body_entered(body):
	body.freeze = true
	body.global_position.y = 50
	body.linear_velocity = Vector2.ZERO
	body.gravity_scale = 0
	await get_tree().create_timer(2).timeout
	body.gravity_scale = 1
	body.freeze = false
:bust_in_silhouette: Reply From: klabri2104

In Godot 4.0, the physics engine has undergone some changes, including the introduction of the new physics process model. To address your issue with the falling objects in your catch the falling objects minigame, I’ll provide an updated approach that works with Godot 4.0.

Instead of directly manipulating the position of the RigidBody2D nodes, we can use the physics engine to simulate the falling and resetting behavior. Here’s an example implementation using the physics process model:

extends RigidBody2D

const FALL_SPEED = 100.0
const RESET_HEIGHT = -200.0
const MIN_X = -200.0
const MAX_X = 200.0

func _physics_process(delta: float) -> void:
    # Move the object downwards
    move_and_slide(Vector2(0, FALL_SPEED))

    # Check if the object has reached the reset height
    if global_position.y >= RESET_HEIGHT:
        # Reset the object's position at the top with a random x-value
        global_position = Vector2(rand_range(MIN_X, MAX_X), RESET_HEIGHT)

In this example, the falling object is a RigidBody2D node. In the _physics_process function, the object is moved downwards using the move_and_slide method, which handles collision and sliding against other objects. The FALL_SPEED constant determines the speed at which the object falls.

Afterwards, we check if the object’s global position (global_position.y) has reached or exceeded the reset height (RESET_HEIGHT). If it has, we reset the object’s position at the top of the screen (RESET_HEIGHT) with a random x value within the range specified by MIN_X and MAX_X.

Ensure that you have configured the collision shapes properly on your objects, and they have the appropriate collision layers and masks set up.

With this approach, the physics engine handles the collision detection and resolution, allowing the objects to behave correctly in terms of collisions and movement.

Awesome, thanks so much! Just asking, could I do a check in this loop with get colliding bodies() to see if the rigid body is colliding with the floor or player instead of a height thing? Cuz I also need to check if the player catches the falling things

RBbooms | 2023-05-29 20:57