[Godot 3.0 Beta 2] How to move a Rigidbody2D towards a mouse using set_linear_velocity?

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By HarryCourt
:warning: Old Version Published before Godot 3 was released.

So, I am stumped. I’m trying to make it so the Rigidbody2D will follow the mouse when picked up, but to no avail. Can someone push me into the right direction?

extends RigidBody2D


# Variables that make it work
onready var spawner = get_node("/root/Scene/Player/Spawner")
onready var canDrag = false
onready var mousePos = get_global_mouse_position()

# Stats
onready var GRAVITY = 200.0
var velocity = Vector2()



func _integrate_forces(state):
	
	# In order to move the object, you have to click it.
	if (Input.is_action_pressed("ui_grabItem") && canDrag == true):
		print("Clicked")
		
		#self.apply_force(Vector2(mousePos), Vector2(mousePos))
		self.set_position(mousePos)



	# Once let go, the RigidBody will fall down to Earth
	if (Input.is_action_just_released("ui_grabItem")):
		
		canDrag = false

# If the mouse is hovering over the object, it can pick it up.
func _on_Item_mouse_entered():
	canDrag = true
:bust_in_silhouette: Reply From: kidscancode

Please read the docs:

Note: You should not change a RigidBody2D’s position or linear_velocity every frame or even very often. If you need to directly affect the body’s state, use _integrate_forces, which allows you to directly access the physics state.

A rigid body is controlled by the physics engine. If you try to make changes to it, the physics will ignore them. You shouldn’t be using _process, you should be using _integrate_forces:

Allows you to read and safely modify the simulation state for the object. Use this instead of Node._physics_process if you need to directly change the body’s position or other physics properties. By default it works in addition to the usual physics behavior, but custom_integrator allows you to disable the default behavior and write custom force integration for a body.

See the rest of the doc for more detail. There is also a tutorial reviewing all of this here: https://youtu.be/J2MItemlTcE It’s for 2.1, but the concepts are the same.

I’ve changed the state, played around with some of the lines shown in the document but to no avail. I’ve updated the code so you can possibly have another look to see what I’m doing wrong?

HarryCourt | 2017-12-24 23:51

I see. I think I misunderstood the question originally. You’re trying to pick the object up and drop it somewhere else. That means that during the dragging process you really don’t want the object to obey physics at all.

Depending on what effect you’re going for, you may need to change the body’s mode property during dragging. MODE_STATIC would let you move it however you like, or MODE_KINEMATIC might be a better choice if you want it to still detect collisions as you drag it around.

When moving it, you want to update the position using set_transform() not position.

kidscancode | 2017-12-25 00:18

No matter what I try, for the life of me I cannot get set_transform to work. Could you just check the code I’ve put down below?

func _integrate_forces(state):

# In order to move the object, you have to click it.
if (Input.is_action_pressed("ui_grabItem") && canDrag == true):
    
    #self.set_position(mousePos)
    self.set_transform(Vector2(mousePos))
    self.MODE_KINEMATIC

HarryCourt | 2017-12-25 10:15

set_transform() doesn’t take a Vector2, it takes a Transform2D:
Transform2D — Godot Engine (latest) documentation in English

The component of the transform that you want to modify to change position is the origin. You want to do something along these lines:

func _integrate_forces(state):
    var xform = state.get_transform()
    xform.origin = mousePos
    state.set_transform(xform)

I use something like this, for example, to make a player’s ship teleport to another location.

kidscancode | 2017-12-26 18:35