I'm currently making spaceship controller script. Control is simple, W/S to move forward/backward, A/D/ to rotate ship by Y Axis(yaw).

Spaceship is RigidBody node and has CollisionShape as children.

Here's the code for move forward/backward:

export var speed = 1
export var max_speed = 10
var current_speed = 0

export var key_acceleration = KEY_W
export var key_deceleration = KEY_S

func process_movement(delta):
    if Input.is_key_pressed(key_acceleration):
        current_speed -= speed * delta
    elif Input.is_key_pressed(key_deceleration):
        current_speed += speed * delta

    current_speed = clamp(current_speed, -max_speed, max_speed)

    linear_velocity = Vector3(0, 0, current_speed)

I need to limit it's maximum speed, so I updated velocity directly, not using something like add_force.

Next is rotating code:

export var yawing_speed = 0.01
export var max_yawing_speed = 0.02
export var yaw_stop_threshold = 0.001
var current_yaw = 0

func process_yaw(delta):
    if Input.is_key_pressed(key_yaw_left):
        current_yaw += yawing_speed * delta
    elif Input.is_key_pressed(key_yaw_right):
        current_yaw += -yawing_speed * delta
        if current_yaw > 0:
            current_yaw -= yawing_speed * delta

            if current_yaw < yaw_stop_threshold:
                current_yaw = 0
        elif current_yaw < 0:
            current_yaw += yawing_speed * delta

            if current_yaw > yaw_stop_threshold:
                current_yaw = 0

    current_yaw = clamp(current_yaw, -max_yawing_speed, max_yawing_speed)   
    rotation.y += current_yaw

In this code, I updated rotation.y directly. Each of this function works if run separately, however run these together, it only changed rotation, not velocity.

func _physics_process(delta):

Change order of process_movement and process_yaw doesn't change anything. If I just run one of process_movement and process_yaw, it works perfectly.

Why my rigidbody ignored velocity and only rotated? Any advice will very appreciate it.


Directly manipulating the velocity of a RigidBody in _physics_process is not supported. From the docs:

The body’s linear velocity. Can be used sporadically, but don’t set this every frame, because physics may run in another thread and runs at a different granularity. Use _integrate_forces as your process loop for precise control of the body state.

You have 3 options to limit the max speed of your body:

1. Use a counter-force

Use add_force for acceleration, and apply a counter-force to slow it down. This counter-force should be proportional to the speed, such that when speed == max_speed, force == counter_force so the forces cancel out and the ship stops accelerating. This is similar to how air resistance works in real life (not that a spaceship would have "air resistance" per se).

I have an example of this from a game jam project I worked on recently (it is MIT-licensed, so feel free to borrow code).

2. Use a KinematicBody

With a KinematicBody, you have are able to precisely control velocity, but you don't get to participate in a full physics simulation. I also have an example of this from the same game, as I decided to switch my ship from a RigidBody to a KinematicBody to get more control over the movement.

3. Use _integrate_forces

You can keep using RigidBody but gain more precise control over its behavior by implementing custom logic in _integrate_forces. The docs discuss this briefly.


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.