Okay, let's start from the top. What is it you expect to happen and what is it you think is happening? I just don't understand what I'm supposed to be looking at in that video.
Vector3 slowing down the velocity
When the transform of a rigid body is changed, the physics integration of that frame is lost. Even just changing the origin's x value will lose the y and z velocity for the frame.
In the docs, it says:
If you only need to place a rigid body once, for example to set its initial location, you can use the methods provided by the Spatial node, such as set_global_transform() or look_at(). However, these methods cannot be called every frame or the physics engine will not be able to correctly simulate the body's state.
Changing one part of the transform is effectively the same as set_global_transform() being called (from what I can tell), so has the same issue.
(I tried debugging into the code to see where that happens, but scons is damn annoying)
One fix is to store the desired x position in a class variable instead of setting the transform directly in the event code. Then add this function:
func _integrate_forces(state):
state.transform.origin.x = mx
where mx is the variable with the mouse x pos. In my tests, that lets the linear_velocity continue working as normal.
Although I don't know if that's going to get the right node, I don't know your hierarchy. But doing that to a simple test fixed the issue for me.
Kojack what is state? is that the cannon?
FluffyPancakes1
_integrate_forces is a built in callback that lets you intercept the physics processing and do your own stuff in there. The state parameter to it is the internal physics state of whatever node (I assume needs to be a physics node like rigidbody) you put the _integrate_forces function on.
If you put it in a script on the rigid body (if that's your cannon) then every time the physics tries to update it will call _integrate_forces and you can manipulate the physics there.
Basically I made a rigid body node and put this script on it:
extends RigidBody
var mx = 0
func _ready():
gravity_scale = 0
linear_velocity = Vector3(0,0,-10)
func _input(event) -> void:
if event is InputEventMouseMotion:
mx = event.position.x/100.0
func _integrate_forces(state):
state.transform.origin.x = mx
The rigid body moves forward along Z and tracks the mouse on X.
If you need precise movement like this (and aren't really using the physics engine, like to bounce on stuff), then you are probably better off just writing the movement by hand.
For some reason, the cannon now doesn't move on the x axis. Here is my code:
extends Node2D
var ended = false
export(Color) var lineColor = Color(255, 0, 0)
export(float) var lineWidth = 5.0
export(bool) var antialiased = false
var change = 0
var xAxisOnCannonAtStart = 0
var position_start := Vector2.ZERO
var touch_down := false
var position_end := Vector2.ZERO
var difference = 0
func _on_input_event(_viewport, event, _shape_idx) -> void:
if event.is_action_pressed("ui_touch"):
touch_down = true
position_start = event.position
func _input(event) -> void:
if not touch_down:
return
if event is InputEventMouseMotion:
if get_parent().get_node("Button").visible == false:
if Input.is_action_pressed("ui_touch"):
if ended == true:
ended = false
else:
ended = false
position_end = event.position
update()
#print("position_end = ",event.position.x)
difference = (-(position_start.x - event.position.x))/100
print("The direction of movement is ",difference," in the x axis")
#print(self.get_parent().get_node("Cannon").transform.origin)
var _zAxisOnCannon = self.get_parent().get_node("Cannon").transform.origin.z
change = difference+xAxisOnCannonAtStart
func _integrate_forces(state):
self.get_parent().get_node("Cannon").transform.origin.x = change
func _process(_delta):
update()
func _draw():
if get_parent().get_node("Button").visible == false:
if Input.is_action_just_pressed("ui_touch"):
touch_down = true
position_start = get_local_mouse_position()
#print("position_start =",get_local_mouse_position().x)
xAxisOnCannonAtStart = self.get_parent().get_node("Cannon").transform.origin.x
if Input.is_action_pressed("ui_touch"):
var mouseLocalPosition = get_local_mouse_position()
draw_line(position_start , mouseLocalPosition, lineColor, lineWidth, antialiased)
here is the hierarchy:
The _integrate_forces function needs to be in a script on the Cannon node, and you need to use the state variable to access the physics state transform (not the transform of a node from get_node())
Although as Cyber said, you might want to do the moving manually. Rigid bodies really don't want you to teleport them around, they want to move using velocity and force so they can bounce off of things. The code would be smaller too.
Kojack
I considered doing it manually, but wouldn't the cannon slow down with lower FPS?
- Edited
FluffyPancakes1
The physics-functions get passed a variable deltatime that has the time passed since the last frame. That is used to equalize the effects of different performances etc.
- Best Answerset by FluffyPancakes1
FluffyPancakes1
That's where the _delta parameter to _process comes in.
_delta is how long it's been (in seconds) since the last call to _process. If your game is running at 100fps, delta will be 0.01s.
If you do add 10 to the transform.origin.z, it would jump 10 units. The faster the fps, the faster the object moves.
But if you add 10*delta, it becomes "10 per second". No matter the fps, it will take 1 second to travel 10 units. (Higher framerates means it takes shorter steps each frame)
So in your _process function you could do:
func _process(_delta):
self.get_parent().get_node("Cannon").transform.origin.z -= 10.0 * _delta
update()
That should move at the same speed as you had with the linear_velocity.
Kojack thanks! That worked like a charm