How do you move RigidBody2D object with codes?
I’m adding a feature to my game where a player character can grab an object, move it with them, and drop it off where you want.
Problem is, unless under special circumstances*, the moved object will simply teleport back to their original position upon being “dropped”. Player can pick it up, move it with them but once dropped it behaves weirdly.
I want the objects to be RigidBody2D so player can collide and interact with them through physics without grabbing them.
*objects will not teleport back (i.e. behaves as desired) if they:
-are playing a sound through audioStreamPlayer2D
-have label node attached
-is constantly printing their global coordinate
here’s the code: extends Node2D#gets player input vector from player parent, used for rotatin - Pastebin.com
Basically the idea is as follows:
-player has a Node2D called “grabbin” which contains “grabRay” (raycast2D for detecting object" and “grabLocation” (sprite2D which acts as a reference point for the grabbed object to be at)
-when a mouse click is detected, the grabRay will detect objects within an area which can be picked up. this will cause the object’s collision to be disabled (so it doesn’t collide with the player) and object’s position to be updated every frame to grabLocation’s global position. This will happen every frame so long as the object is being carried around.
-if player decides to drop it, they’ll click their mouse again. This will stop the object’s location to be updated any more, and re-enables the object’s collision.
I’ve added stuff since this post so sorry for the difference, though the only difference should be sound effects that play
extends Node2D
#gets player input vector from player parent
var input_vector: Vector2 = Vector2.ZERO
@onready var parentObject: CharacterBody2D = $".."
func player_control_vector():
return parentObject.input_vector
#handles rotation of grabbing node
func grab_rotate(inputVector):
#rotates grabbing node
if inputVector != Vector2.ZERO:
set_rotation(inputVector.angle() - PI/2)
#plays sound based off of name give
@onready var nopeShort: AudioStreamPlayer2D = %nopeShort
@onready var nopeBeep: AudioStreamPlayer2D = %nopeBeep
@onready var pickup: AudioStreamPlayer2D = %pickup
@onready var drop: AudioStreamPlayer2D = %drop
func sound_play(soundType):
if soundType == "nopeShort":
nopeShort.play()
elif soundType == "nopeBeep":
nopeBeep.play()
elif soundType == "pickup":
pickup.play()
elif soundType == "drop":
drop.play()
#handles the grabbing nitty gritty
@onready var grabLocation = %grabLocation #location where grabbed item will go, in front of player
@onready var grabRay = %grabRay #detects grabbable items
@onready var obstacleRay: ShapeCast2D = %obstacleRay #detects obstacle which hinders item droping
var isHandEmpty: bool = true
var collider: Object = null #object that could be picked up
func grab_object():
if not isHandEmpty: #if player is carrying something, it is moved to player's front
collider.global_position = grabLocation.global_position
if Input.is_action_just_pressed("input_left_click"):
if isHandEmpty: #trying to pick up stuff
if grabRay.is_colliding(): #hand is empty and there's something to grab
collider = grabRay.get_collider(0) #selects first item to collide with ray
collider.set_collision_layer(9) #makes the object non-colliding
isHandEmpty = false
if collider != null:
collider.freeze = true
sound_play("pickup")
elif not grabRay.is_colliding(): #tryna pick up stuff when there's nothing
sound_play("nopeShort")
#tries to drops the carried item
elif not isHandEmpty : #player is carrying something
if obstacleRay.is_colliding(): #trying to drop but there's object in the way
sound_play("nopeBeep")
else: #trying to drop something and nothing's in the way
collider.global_position = grabLocation.global_position #this code doesn't change anything
collider.set_collision_layer(256) #somehow puts the object back to their collision layer
isHandEmpty = true
collider.freeze = false
sound_play("drop")
func _physics_process(_delta: float) -> void:
grab_rotate(player_control_vector())
grab_object()
Theres always some weird behaviour when moving physicsbodies directly. I tried a similar grabbing system, but i reparented the rigidbody to the player and reparented it back when i dropped it, which worked (although there was sometimes some weird behaviour). In the end i only reparent the texture and hide the rigidbody and reverse this when dropping it. The things is i then set the global_position of the rigidbody and that works for me
You also might want to try a different approach eventhough there should be no reason it should teleport back