(GDScript) set_linear_velocity Relative to the Object (local), not global!

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

Local Movement with Physics

I can’t figure a way to Locally set_linear_velocity() to my Rigidbody object. When I use set_linear_velocity, it only works on Global axis…

I really need a hand on making my Rigidbody Player move (with physics forces) along his own axis (X, Y and Z), or a turn around would be great to!!

My goal is to create a controller wich can make the player move like a ‘Vessel’ in the 3D environment. Here is my piece of code (only for the X axis as a test):

func _move_player():
# Define the Inputs in variables
btn_right = Input.is_action_pressed("controller_right") # created inputs
btn_left = Input.is_action_pressed("controller_left")

# Check if you are not moving on a particular axis to create a brake fx
if btn_right or btn_left:
	movingOnX = true
else:
	movingOnX = false

# Code from Jospic from GitHub (thanks)
var linearVelocityModule = 100 
var anglePlayerRot = self.get("transform/rotation") # get_rot() not working!
var localLinearVelocityX = linearVelocityModule * cos(anglePlayerRot.x) #Can't convert Vector3 to Float!!
var localLinearVelocityY = linearVelocityModule * sin(anglePlayerRot.y)

# Trying this for 3D
var localLinearVelocityZ = linearVelocityModule * tan(anglePlayerRot.z)
var localLinearVelocity = Vector3(localLinearVelocityX, localLinearVelocityY, localLinearVelocityZ) 

# Apply Velocities
# If you press on A or D...
if movingOnX:
	# If you actually press D
	if btn_right:
		set_linear_velocity(Vector3(localLinearVelocity.x - speed, get_linear_velocity().y, get_linear_velocity().z))
	# If you actually press A
	elif btn_left:
		set_linear_velocity(Vector3(localLinearVelocity.x + speed, get_linear_velocity().y, get_linear_velocity().z))
# If you are not pressing on A or D... Brake fx
else:
	if v.x != 0:
		set_linear_velocity(Vector3(localLinearVelocity.x * brake_damper, get_linear_velocity().y, get_linear_velocity().z))

If you have any ideas or tutorials to share with me… Feel free to correct all of it!

Thx, Math

There is an easiest way to do it.

var speed = 3    #---set your speed here
var a = state.get_transform().basis
set_linear_velocity(Vector3(a.x.z, a.y.z, -a.z.z) * speed)

#–This code will works to axis Z
#–To use another axis just multiply the Vectors you want to use
Vector3(a.x.z, a.y.z, -a.z.z) * Vector3(a.x.x, a.y.x, -a.z.x)

var speed = 3
var a = state.get_transform().basis
var z = Vector3(a.x.z, a.y.z, -a.z.z)
var y = Vector3(a.x.y, a.y.y, -a.z.y)
set_linear_velocity((y * z) * speed)
#---Just be aware...any number Multiplied by zero is = zero, so check if the angle of your ship is not equal to zero. in this case turn your 0 to 1 or your ship won't move.

#-- angular velocity works almost the same way.
var speed_spin = 2
var a = state.get_transform().basis.x
set_angular_velocity(Vector3(a.x, a.y, a.z) * speed_spin)

Malkavian_7 | 2017-05-27 23:33

:bust_in_silhouette: Reply From: jospic

You know angular rotation of your Player, and you can set linear velocity along Player two direction components:

   var linearVelocityModule = 100
    var anglePlayerRot = get_node("Player").get_rot()
    var localLinearVelocityX = linearVelocityModule * cos (anglePlayerRot)
    var localLinearVelocityY = linearVelocityModule * sin (anglePlayerRot)
    get_node("Player").set_linear_velocity(Vector2(localLinearVelocityX, localLinearVelocityY))

.j

Well it did’nt work :frowning: But thanks a lot!

First, get_rot is not existing in base Rigidbody… I tried get_rotation() and get_rotation_deg() but it results in weird behaviours :frowning:

I forgot to mention that my project is in 3D… My bad! I really tried to make it work, but…

I will need more help :frowning:

MathieuJazz | 2016-06-02 03:24

If you want to get a property that is editable in the editor inspector, use the function get()

enter image description here

In that case : get_node("Player").get("transform/rotation")

Matt_UV | 2016-06-02 14:06

I tried it, and I failed! I can’t figure a way to do it.
I’ve inserted my own piece of code… Let’s see if someone can figure this out!
Thx

MathieuJazz | 2016-06-02 19:06

adding a thank you to this. For Godot 3.0 I used it as such and it works great:

var linearVelocityModule = 100
var anglePlayerRot = bullet.rotation
var localLinearVelocityX = linearVelocityModule * cos (anglePlayerRot)
var localLinearVelocityY = linearVelocityModule * sin (anglePlayerRot)
bullet.linear_velocity = Vector2(localLinearVelocityX, localLinearVelocityY)

Robster | 2018-02-22 03:58