Godot Version
v4.2.2
Question
I’m trying to set the .position of my player object and when I do it blips at the spot for a moment and goes back to falling where it was
The deathbox collider is the bottom blue box collider(teleports player):
Nodes (the deathbox is unnamed rn so its just CollisionShape2D):

Closeup with visible player:
The player blipping on screen for a frame when tp is attempted:
Code to tp player (at bottom, it comes from an on collide with body trigger on the deathbox):
extends Node2D
# mostly for the cards
@onready var scac = %ScaleContainer
@onready var player = %Player
#@onready var ctext = $Cardtext
@onready var SBC = %ScaleBcon
@onready var gamen = get_tree().get_root().get_node("Game")
#@onready var CTexture = $CardTexture
# Cool hand stuff
@onready var hand = $Camera2D/Hand/Handanimator
@onready var handn = $Camera2D/Hand
@onready var handcool = $Handcool
# ledges
@onready var eledge = $Ledges/Endledge
@onready var sledge = $Ledges/Startledge
@onready var CCon = $Camera2D/Cardcontainer
signal loaded
var starty := 300.0
var startyt := 300.0
var endx := 360.0
var endxt := 360.0
var difficulty = 0
var tdiff = 0
var handst = false
var cardcount = 3
var itstop = false
var canstop = true
var Mprotoscale = load("res://protoscalemenu.tscn")
var card = load("res://propcard.tscn")
@export var invent = []
@export var proplist = {}
func Cselected():
hand.play("handanim")
for i in CCon.get_child_count():
CCon.get_child(i).queue_free()
handst = false
func loadlvl(idif):
startyt = starty
endxt = endx
tdiff = difficulty
glvl()
sledge.position.y = startyt
eledge.position.x = endxt
player.position = Vector2(-480,-starty + 300)
SBC.visible = true
handst = true
hand.play("handin")
for i in cardcount:
var instance = card.instantiate()
instance.position = get_global_mouse_position()
instance.scac = scac
instance.player = player
instance.SBC = SBC
instance.gamen = gamen
CCon.add_child(instance)
if idif:
difficulty += 1
func glvl():
var choice = randi_range(0,2)
if choice == 0:
tdiff -= 1
if choice == 1:
startyt -= randi_range(-40,5)
tdiff -= 0.5
if choice == 2:
endxt += randi_range(-40,5)
tdiff -= 0.5
if tdiff > 0:
glvl()
# Called when the node enters the scene tree for the first time.
func _ready():
loadlvl(true)
# Called every frame. 'delta' is the elapsed time since the previous frame.
func _process(delta):
if itstop:
Engine.time_scale = 0
else:
Engine.time_scale = 1
if canstop && ((handn.rotation == 134.4 && handst) || (handn.rotation == 0 && !handst)):
itstop = true
else:
itstop = false
if Input.is_action_just_pressed("RClick"):
loadlvl(true)
print(player.position)
func _on_button_pressed():
pass
#if itstop && canstop:
#itstop = !itstop
#canstop = !canstop
func _on_area_2d_body_entered(body):
player.position = Vector2(-480,-starty + 300)
player.linear_velocity = Vector2.ZERO
Rigid bodies don’t like being teleported, you will want to avoid altering position directly wherever possible. In this case to force teleporting you will have to queue the teleport until a _integrate_forces
override can handle it. Add this to your player script, then use player.queue_teleport =
instead of position.
var queue_teleport: Vector2
func _integrate_forces(state: PhysicsDirectBodyState2D) -> void:
if queue_teleport != Vector2.ZERO:
state.transform = Transform2D(0.0, queue_teleport)
state.linear_velocity = Vector2.ZERO # also only edit linear_velocity in _integrate_forces
queue_teleport = Vector2.ZERO
1 Like
I don’t actually understand what this does or how to use it. You said to replace player.position with player.queue_teleport but I don’t understand and it also throws an error. How does this work? (_integrate_forces, → void, state)
var queue_teleport: Vector2
func _integrate_forces(state: PhysicsDirectBodyState2D) -> void:
if queue_teleport != Vector2.ZERO:
state.transform = Transform2D(0.0, queue_teleport)
state.linear_velocity = Vector2.ZERO # also only edit linear_velocity in _integrate_forces
queue_teleport = Vector2.ZERO
func Cselected():
hand.play("handanim")
for i in CCon.get_child_count():
CCon.get_child(i).queue_free()
handst = false
func loadlvl(idif):
startyt = starty
endxt = endx
tdiff = difficulty
glvl()
sledge.position.y = startyt
eledge.position.x = endxt
player.queue_teleport = Vector2(-480,-starty + 300)
Is this script part of the player? Only the player (a RigidBody2D) should have the _integrate_forces
function.
queue_teleport
is a variable storing the teleport position, if it’s ZERO it’s assumed to be “empty” and has nothing to queue. It uses _integrate_forces
’ state
to change the player object during the physics thread.
Ohh I put it on the game node oops
The game node was handling tp but yeah I can send a signal to player I think
You won’t need to signal the player, that’s why your changing player.queue_teleport
just like you would change player.position
So I put this in the game node where it was tping the player
func loadlvl(idif):
startyt = starty
endxt = endx
tdiff = difficulty
glvl()
sledge.position.y = startyt
eledge.position.x = endxt
player.queue_teleport(-480,-starty + 300)
SBC.visible = true
handst = true
And I put this in the player
#curses
var lessjump = 0
var lessspeed = 0
var queue_teleport: Vector2
func _integrate_forces(state: PhysicsDirectBodyState2D) -> void:
if queue_teleport != Vector2.ZERO:
state.transform = Transform2D(0.0, queue_teleport)
state.linear_velocity = Vector2.ZERO # also only edit linear_velocity in _integrate_forces
queue_teleport = Vector2.ZERO
func _ready():
pass # Replace with function body.
func _process(delta):
isccol = raca.is_colliding() || raca2.is_colliding()
But it’s throwing and error and I bet I’m being an idiot (or this is some big complex bit like messing with the processing order directly)
It’s a variable, not a function. Use assignment, just like player.position
player.queue_teleport = Vector2(-480,-starty + 300)
Make sure to post the error message you recieve and the relevant line.
Not fixed,
The car still blips and doesnt tp, line is
player.queue_teleport = Vector2(-480,-starty + 300)
and there’s no error now though
(Code in player:)
#curses
var lessjump = 0
var lessspeed = 0
var queue_teleport: Vector2
func _integrate_forces(state: PhysicsDirectBodyState2D) -> void:
if queue_teleport != Vector2.ZERO:
state.transform = Transform2D(0.0, queue_teleport)
state.linear_velocity = Vector2.ZERO # also only edit linear_velocity in _integrate_forces
queue_teleport = Vector2.ZERO
func _ready():
pass # Replace with function body.
func _process(delta):
isccol = raca.is_colliding() || raca2.is_colliding()
Interesting, does the _integrate_forces ever run? Could you add a print statement to test?
func _integrate_forces(state: PhysicsDirectBodyState2D) -> void:
if queue_teleport != Vector2.ZERO:
print("teleporting transform: ", queue_teleport)
state.transform = Transform2D(0.0, queue_teleport)
state.linear_velocity = Vector2.ZERO # also only edit linear_velocity in _integrate_forces
queue_teleport = Vector2.ZERO
The function runs, but the if statement only runs right at game start hmmm (I used print(“:D”) to test)
Is there any reason queue_teleport
would be set to ZERO? Would you normally teleport the player to ZERO?
No the player starts at this pos