0 votes

I'm making a multiplayer car/racing game, and I want it to detect when the cars hit each other and maybe make the other car get pushed back a little and play a sound?

Godot version v3.4.4.stable.official [419e713a2]
in Engine by (193 points)

1 Answer

0 votes

Easily done. I assume you're using a KinematicBody2D? If you use the physics engine it'll pass a collision object to you. To do this, use the _physics_process(delta) method (not _process(delta)) with move_and_slide() - that slides by default but you can add your own behaviour.

Something like this:

func _physics_process(delta):
    velocity = move_and_slide(velocity*delta)
    if get_slide_count():
        var collision = get_slide_collision(0)
        print(collision.collider.name) 
        velocity = -velocity #just a simple example

Check the docs for what info the collider obj can give you. The collider.normal is probably the most helpful thing - that's the vector perpendicular to what you just hit.

There's also move_and_collide() that has different inbuilt behaviour. Personally I don't like it as much but your mileage my vary.

by (1,877 points)

Actually, I am doing 3D, and I am using a VehicleBody node for the cars :)

Ah, the 3d doesn't change anything but the VehicleBody does as it inherits from RigidBody. You need to make sure that contact_monitor is enabled, set contacts_reported to a positive int and use the body_entered signal. You need to add motion with forces / impulses instead of directly moving the car

Here's my code:

steering = lerp(steering, Input.get_axis("right", "left") * 0.4, 5 * delta)
#steering = Input.get_axis("right", "left") * 0.4
#engine_force = Input.get_axis("forward", "backward") * 100
var acceleration = Input.get_axis("forward", "backward")
var rpm = $back_left_wheel.get_rpm()
$back_left_wheel.engine_force = acceleration * max_torque * (1 - rpm / max_rpm)
rpm = $back_right_wheel.get_rpm()
$back_right_wheel.engine_force = acceleration * max_torque * (1 - rpm / max_rpm)

I set the contact monitor to true and the contacts_reported to a positive integer, is there any way you could give me an example of what to do?

Are you picking up the collision? Select the VehicleBody node, on the right go to the "Node" tab. Double click on "body_entered(body: Node)", select your VB script. That gets you this:

func _on_car_body_entered(body):
    apply_central_impulse(Vector3.UP * 10000)
    printt("Weeeeeeeeeeeee! I hit ", body.name)

Obviously just add whatever linear algebra you need to get the behaviour you're after.

If you want to do something more advanced you can use _integrate_forces(state). I used it for an amphibious craft so you can newtonian gravity / buoyancy / thrust from the rotating outboard motor etc. Unfortunately there's no visualisation in the editor so this is advanced. You probably just want a simple impulse.

Welcome to Godot Engine Q&A, where you can ask questions and receive answers from other members of the community.

Please make sure to read How to use this Q&A? before posting your first questions.
Social login is currently unavailable. If you've previously logged in with a Facebook or GitHub account, use the I forgot my password link in the login box to set a password for your account. If you still can't access your account, send an email to webmaster@godotengine.org with your username.