How can I retrieve the name of a colliding body

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By treetertot

How would I find the name of a colliding KinematicBody2D from within a KinematicBody2D

If you’re looking for how to get names of nodes in general, the Node class (which pretty much everything inherits from) has a name member and a get_name() method. get_name doesn’t show up on the online docs page, but it is in the “Classes” documentation that’s in the godot editor.

markopolo | 2018-04-05 19:14

:bust_in_silhouette: Reply From: kidscancode

It depends on whether you’re moving with 1)move_and_collide() or 2)move_and_slide(). This should get you started:

func _physics_process(delta):
    var collision = move_and_collide(velocity * delta)
    if collision:
        print(collision.collider.name)
func _physics_process(delta):
    move_and_slide(velocity)
    for i in range(get_slide_count() - 1):
        var collision = get_slide_collision(i)
        print(collision.collider.name)

In either case, you’re eventually getting a KinematicCollision2D object that contains the information about the colliding body.

Could you please comment on the efficiency of both method.

To me it seems that the first method is faster because it uses build-in methods and therefore less look-ups, but it reports only one collision (the first one as it seems).

The second method allows to gather all collisions, but since it requires ‘get_slide_count’, and n times ‘get_slide_collision’ it seems that it could get quite slow.

Which method would you command? Is the second one acceptable in real-case games?

Is there a build-in methods that returns an array of colliders? Are there some C functions that does the job?

AGy | 2019-09-11 23:35

In Godot 3, it seems that for i in range(get_slide_count() - 1): should be replaced by for i in range(0, get_slide_count()): is that correct?

AGy | 2019-09-11 23:35

As with any array, the index is from 0, and range() automatically starts at 0 if you don’t specify. The -1 was a typo. However, you don’t even need range(), you can do this for the same result:

for i in get_slide_count():

As for your other question, of course the second method is acceptable - why wouldn’t it be? move_and_collide() only handles movement and stops on the first collision. There can’t be an “array of colliders” because movement stops as soon as one is hit.

move_and_slide() performs a common collision response that you’d otherwise have to code yourself (sliding along a colliding body). This can result in multiple collisions in one frame (such as in a corner), so you get an array of one or more collisions, which you iterate through with get_slide_collision().

Stop thinking about performance until you actually have a performance problem. This is unlikely to ever be an issue.

kidscancode | 2019-09-11 23:48

@kidscancode

Thank you for the comment, it is good to know.

Stop thinking about performance until you actually have a performance problem. This is unlikely to ever be an issue.

I am currently checking if godot could be a good alternative to the engines I am currently using, and I am trying to understand what is the logic behind the scene. Because there are plenty of ways of doing the same thing, it is a bit misleading – especially because I got overwhelmed by the variety of solutions found in the demos.

I am looking for the proper answer for my current purpose. I had several experiences with Script language before and as soon as one starts to code specific functions with the high level API things get amazingly slow. I was wondering if it would be the same with godot and if I was not already starting to do the same with the example posted above.

I have one additional question if you don’t mind:

Yesterday, I found that RigidBody2D has a method called get_colliding_bodies() that returns an Array of Nodes colliding with the Body. But I am not quite sure if this type of node should be used in a Kinematic platformer, I guess RigidBody is meant for Dynamic games, is that correct?

thank you for your time.

AGy | 2019-09-12 15:56

Rigid body is meant for objects for which you want full physics. A rigid body’s movement is determined by the physics engine. Generally speaking, you should not move a rigid body manually, but rather apply forces and the physics engine will take care of the results.

Kinematic bodies are typically used for things like platformers because they give you more control. The tradeoff is that you must code things like gravity, friction, and collision response yourself.

This document is a good summary of the different types of collision objects:
Physics introduction — Godot Engine (latest) documentation in English

There are also specific docs in that section with more detail on each of the body types.

kidscancode | 2019-09-12 16:02

Thanks for the link this was exactly what I was looking for.

I originally asked about retrieving the name/object of the colliding objects in order to differentiate collisions between various environmental objects. The player should react differently with floors, doors, collectables… I ended up coding the following:

# This seems to be the best choice.
velocity = move_and_slide(velocity, Vector2(0, -1))

for i_collision in range(0, get_slide_count() - 1):
	var collision = get_slide_collision(i_collision)
	var obj : Node2D = collision.collider
		
	match obj.get_groups():
		[deadly_zone]:
			...
        [exit_zone]:
            ...
        [collectors]:
            ...
		_:
			pass

Which after reading the link you send me (as I was suspecting) is NOT what one should do. correct?

To my understanding the proper way is to make use of layers and masks( documentation) which is exactly what I would have coded in low level languages like C/C++ or C#.

The question is now how do I know from which layer the collision came?
How can I detect the type/group/mask of the collider to trigger different behaviors?

Again, I thank you for your time.

AGy | 2019-09-13 00:46

Alright,

It seems that I am not the only one being mislead by the collisions in godot. It might be that I have been wrongly implementing collision in all my game so far… :stuck_out_tongue:

As I now understand it… No! I do not understand, as it seems to me…
in Kinematic games collisions are only meant for motion.
Detecting who collides with what is done with Area2D, with the body_entered signal.

# player.gd ------------------------------------------
func _on_Player_dying():
    # trigger dying animation
    ...

# coins.gd -------------------------------------------
func _on_Area2D_body_entered(body):
    # test who has entered
    match body.get_groups():
        [players]:
            # collect coins
            ...
        [enemies]:
            # destroy coins
            ...

# deadly_trap.gd -------------------------------------
func _on_Area2D_body_entered(body):
    # test who has entered
    match body.get_groups():
        [players]:
            # trigger death
            body.emit_signal("DIE!!!")

The question is now is that any better than what I proposed in my last comment?
Am I not mixing two concepts here? Are groups meant for collision segregation?

I think a tutorial or a Demo would necessary.

Thank again,

AGy | 2019-09-13 00:46