game development - How to make a CharacterBody3D bounce off a wall in an opposite direction in Godot 4.3 - Stack Overflow

admin2025-04-17  2

I know this is a common question for this topic, but I have tried everything I have found online and I just don't know what I am doing wrong. I started with Godot a few days ago, and I'm making a small multiplayer tank game. I want to get the bullets to bounce off the wall in the other direction. ]()

extends CharacterBody3D

const SPEED = 20.0

# Called every frame. 'delta' is the elapsed time since the previous frame.
func _physics_process(delta):
    position += transform.basis * Vector3(0, 0, -SPEED) * delta
    var collision = move_and_collide(velocity * delta)
    if collision:
        print(collision.get_collision_count())
        velocity = velocity.bounce(collision.get_normal())

This is the code I've used for trying to make it bounce off the wall, and although it does seem to collide with the walls, it just goes over it and past it. You can see it in the video here. Any ideas? Am I using the bounce() function in the wrong way? Or am I not doing enough?[See the video of the result here

I know this is a common question for this topic, but I have tried everything I have found online and I just don't know what I am doing wrong. I started with Godot a few days ago, and I'm making a small multiplayer tank game. I want to get the bullets to bounce off the wall in the other direction. ](https://imgur.com/a/k2IneCv)

extends CharacterBody3D

const SPEED = 20.0

# Called every frame. 'delta' is the elapsed time since the previous frame.
func _physics_process(delta):
    position += transform.basis * Vector3(0, 0, -SPEED) * delta
    var collision = move_and_collide(velocity * delta)
    if collision:
        print(collision.get_collision_count())
        velocity = velocity.bounce(collision.get_normal())

This is the code I've used for trying to make it bounce off the wall, and although it does seem to collide with the walls, it just goes over it and past it. You can see it in the video here. Any ideas? Am I using the bounce() function in the wrong way? Or am I not doing enough?[See the video of the result here

Share Improve this question asked Jan 31 at 22:56 Angel AndradeAngel Andrade 1
Add a comment  | 

1 Answer 1

Reset to default 1

These two lines can move the bullet:

    position += transform.basis * Vector3(0, 0, -SPEED) * delta

This line moves the bullet (until it collides):

    var collision = move_and_collide(velocity * delta)

Pick one.


Futhermore, the code that runs when there is a collision updates velocity using bounce... But the first line does not use velocity (the direction is based on transform.basis instead), so that line will continue moving the bullet in the same direction.

In fact, I suspect that your velocity is zero. So only the first line is actually moving the bullet. And no collision is detected.

Thus, you want to give an initial value to the velocity. For example:

func _ready() -> void:
    velocity = global_transform.basis * Vector3(0, 0, -SPEED)

Here I'm using global_transform, because velocity is always in global space.

And use that velocity to move the bullet, so that when you detect the collision, it actually changes direction.


My recommendation is to stick with move_and_collide, since you want to react to the collition. The code would be like this:

func _ready() -> void:
    velocity = global_transform.basis * Vector3(0, 0, -SPEED)

func _physics_process(delta: float) -> void:
    var collision := move_and_collide(velocity * delta)
    if collision != null:
        velocity = velocity.bounce(collision.get_normal())

Notice here the line updating position has been removed.


Alternatively, if you do not want move_and_collide to move the bullet, then pass true on the test_only parameter (which is the second parameter of move_and_collide).

In this case, you need to update the first line to use velocity:

func _ready() -> void:
    velocity = global_transform.basis * Vector3(0, 0, -SPEED)

func _physics_process(delta: float) -> void:
    var collision := move_and_collide(velocity * delta, true)
    if collision != null:
        print(collision.get_collision_count())
        velocity = velocity.bounce(collision.get_normal())

    global_position += velocity * delta

As you might have guessed, here I'm using global_position because velocity is always in global space.


Finally, presumably you want the bullet to rotate. The simplest way to do that would be use look_at after you update the velocity:

velocity = velocity.bounce(collision.get_normal())
look_at(global_position + velocity, up_direction)

Now, I believe that is correct, but if the result is that the bullet is looking backwards, you want to pass a true to the third parameter of look_at:

velocity = velocity.bounce(collision.get_normal())
look_at(global_position + velocity, up_direction, true)

That basically flips the orientation.

转载请注明原文地址:http://anycun.com/QandA/1744844064a88407.html