Node Position Updates for a Frame and Then Goes Back to Original Position

Godot Version

v4.3.stable

Question

I am trying to implement a system where the player clicks on a resource to pick it up and then put it down somewhere else. Currently, the way I do that is once the body is clicked, it disables the CollisionBody. Then when the player clicks it changes the position of the object’s position to the mouse position. In it’s current state, the object stays visible the whole time, but I want to toggle the object’s visibility. If I change the visibility to be false when the object is clicked, and then make the visibility true again when the object is placed back down, the object will move to the mouse position for a frame, then “teleport” back to the original location.

The code for the resource being moved. Bug appears to be in check_if_hovered():

class_name WoodResource 
extends GameResource


@onready var game_manager = get_tree().get_nodes_in_group("GameManager")
#@onready var wood = load("res://Resources/wood.tscn")
#is_fuel : bool = true

var imp_dir : Vector2
var imp_dir_x : int
var imp_dir_y : int


# Called when the node enters the scene tree for the first time.
func _ready():
	add_to_group("Resources")
	impulse_on_spawn()


# Called every frame. 'delta' is the elapsed time since the previous frame.
func _process(_delta):
	check_if_hovered()


func _on_mouse_entered():
	is_hovered = true

func _on_mouse_exited():
	is_hovered = false

func check_if_hovered():
	if is_hovered:
		if Input.is_action_just_pressed("pick_resource"):
			if GameManager.append_clicked_resource(self):
				#%CollisionShape2D.set_deferred("disabled", true)
				%CollisionShape2D.disabled = true
				#self.set_deferred("visible", false)
				#self.visible = false #This line is causing the bug where when 
					#the item becomes visible again, it teleports back to the
					#original spot.

func impulse_on_spawn():
	#Adds an impulse in a random direction. This is to more randomly distribute
		#resources when they spawn instead of stacking up in a line.
	imp_dir_x = randi_range(-64,64)
	imp_dir_y = randi_range(-64,64)
	imp_dir = Vector2(imp_dir_x,imp_dir_y)
	#print(imp_dir)
	apply_impulse(imp_dir)

At the moment all GameResource does is extend RigidBody2D. The commented lines show the various attempts I have made toggle visibility.

Below is the GameManager code that is referenced by the GameManager.append_clicked_resource(self):

class_name GameManager
extends Node


static var mouse_inventory : Array[GameResource]
static var mouse_inv_textures : Array[Node]
static var mouse_inv_max_size : int = 5
static var last_clicked = null

# Called when the node enters the scene tree for the first time.
func _ready():
	mouse_inv_textures = get_tree().get_nodes_in_group("MouseInvTextures")
	#mouse_inventory.resize(mouse_inv_max_size)
	#print(mouse_inventory)


# Called every frame. 'delta' is the elapsed time since the previous frame.
func _process(_delta):
	if Input.is_action_just_pressed("place_resource"):
		place_held_resource()


static func append_clicked_resource(resource: GameResource) -> bool:
	#Call this function in the resource that is clicked, when it is clicked.
	#For reference see wood_resource.gd line 3 of check_if_hovered()
	last_clicked = resource
	if mouse_inventory.size() < mouse_inv_max_size:
		mouse_inventory.append(last_clicked)
		add_resource_to_inv(mouse_inventory)
		#last_clicked.set_deferred("visible", false)
		#last_clicked.visible = false
		print("Mouse Inv: ", mouse_inventory)
		return true
	else:
		print("Mouse Inv: ", mouse_inventory)
		return false

static func add_resource_to_inv(resource_array):
	#Get texture to add to inventory
	var index = resource_array.size() - 1
	var resource = resource_array[index]
	var resource_texture = resource.get_node("TextureRect").texture
	#Add the texture to the MouseInventory node
	mouse_inv_textures[index].texture = resource_texture
	

func place_held_resource():
	var last_element = mouse_inventory.size()-1
	if last_element >= 0: #Make sure we are not calling element -1
		var last_item_picked = mouse_inventory[last_element]
		var camera = %Camera2D
		var mouse_pos = camera.get_global_mouse_position()
		var last_item_collision = last_item_picked.get_node("CollisionShape2D")
		print("Pick up pos: ", last_item_picked.position)
		last_item_collision.disabled = false
		last_item_picked.visible = true
		last_item_picked.position = mouse_pos
		#last_item_picked.set_deferred("position", mouse_pos)
		mouse_inv_textures[last_element].texture = null
		mouse_inventory.remove_at(last_element)
		print("Mouse Pos: ", mouse_pos)
		print("Placed Pos: ", last_item_picked.position)
	print("Mouse Inv: ", mouse_inventory)

I don’t really know much about static typing, but it was the only way I could get the editor to not throw an error at me. So hopefully that is not my issue. Let me know if I need to provide information. I wrote this right before bed too, so hopefully it is cohesive and makes sense.

RigidBodies do not like being edited directly outside of physics calls.You could probably get away with freezing the rigidbody (may need to be deferred) then placing it and un-freezing it

1 Like

Freezing when clicked and unfreezing after it was moved worked perfectly. Thank you.

1 Like

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