Can't set position more than once

Godot Version

4.3

Question

I have a very simple game with a Player that should be reset to the same position when you press forward. The Player is in freefall, so they are pulled down by gravity.

However, when I run this, it only sets the position once. After that it doesn’t ever set the position at all. Also, the print_debug statement to print the position never prints it correctly. It always says it is (0,20,0)

func _physics_process(delta: float) -> void:
	if Input.is_action_just_pressed("forward"):
		$Player.position = Vector3(0,20,0)
		
	if Input.is_action_just_released("forward"):
		print_debug($Player.position)
		$Player.remove_child(box_instance)

What am I doing wrong here? Is there a standard way to set the position of a scene? Is there a standard way to get the position of a scene for debugging purposes other than this?

Thanks!

1 Like

Is there a script present on $Player that overrides your system in the script you’ve presented? That would be one possible reason for your issue.

If the $Player is a physics body it may also be worth noting that you should not directly modify its state from another node. Similarly, you should not use _physics_process() to directly modify the physics state of a node (by directly I mean setting the position, rotation). Use _integrate_forces() instead for this purpose.

You should also not use _physics_process() to detect input. The update rate of the physics loop is not sufficient for detecting an input at the exact time you press your input. Either use _process(), _input(), or _unhandled_input() for input handling.


These are just general issues that I see in your script. Please fix these issues and report back whether your issue is resolved.

2 Likes

You set the position to (0,20,0) every time and that’s wrong, you need to initialize it based on the current position:

$Player.position += Vector3(0,20,0)
1 Like

I have removed all other scripts from the game (it is very simple; I am trying to learn Godot) and placed this behavior in _process, but it still behaves the same. I am only able to set the position once, and reading the position still does not work.

I tried placing the behavior in _integrate_forces(), but it does not work at all there.

What is the expected way to reset an object’s position in game (for an object that uses physics)? Also, what is the expected way to read an object’s position in game?

Thanks!

Using += does actually change things. However, it doesn’t quite do what I want.

It appears to directly shift the Player up by 20 meters every time. I am trying to reset the player’s position to (0,20,0) every time I press forward.

Also, $Player.position (and $Player.global_position) now goes up by 20 units every time, but still doesn’t actually account for other Player movement
image

See here for learn it.

1 Like

I got it to work! I am now able to manually reset the player’s position.

The answer was to use _integrate_forces as @Sweatix had suggested, but what I was missing was that the script needed to be on the player object. I placed it on the RigidBody3D that is the basis for the Player’s physics.

The code below works correctly, including correct printing of the player’s global position.

Thanks for the help!


func _integrate_forces(state: PhysicsDirectBodyState3D) -> void:
	if Input.is_action_just_pressed("forward"):
		self.global_position = Vector3(0,20,0)
		print_debug(self.global_position)
		
	if Input.is_action_just_released("forward"):
		print_debug(self.global_position)
		self.global_position = Vector3(0,100,0)

1 Like

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.