How to get a KinematicBody2D's collider's collision

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By lavaduder
:warning: Old Version Published before Godot 3 was released.

I have two kinematic bodies ramming into each other in a scene. I want it so that if one kinematicbody detects the other, it will respond and load a script, however I can’t seem to detect the other’s presence. (Since the metadata is constantly returning zero). How does one detect collision in kinematicbody.

tool
extends KinematicBody2D
#Characteristics
export var hp = 1
export var damage = 1
#enum statuseffect {normal,damaged,cutting,poison,fire} 
#var priority = 0
export var speed = 1
export var power = 1
export var defense = 1
#Movement
export var playercontroler = 0
export var vel = Vector2()
export var gravity = 0
export var agility = 1000
#Children Nodes
onready var charspr = get_node("colid/sprite")
onready var hitbox = get_node("hitbox")
#Effects
export var speedcolor = Color("07ff00")
export var powercolor = Color("ff0000")
export var defensecolor = Color("1300ff")
export var normalcolor = Color("ffffff")


func _ready():
	set_fixed_process(true)
	pass

func _fixed_process(delta):
	#Input
	var mover = Input.is_action_pressed(str(playercontroler) + "right")
	var movel = Input.is_action_pressed(str(playercontroler) + "left")
	var attspeed = Input.is_action_pressed(str(playercontroler) + "attackspeed")
	var attpower = Input.is_action_pressed(str(playercontroler) + "attackpower")
	var attdefense = Input.is_action_pressed(str(playercontroler) + "attackdefense")
	#Input X axis
	if (mover):#mover
		vel.x = agility
	elif (movel):
		vel.x = -agility
	else:
		vel.x = 0
	#Input Y axis
	vel.y += gravity
	#Input Attack
	if (attspeed):
		add_to_group("speed")
		if charspr != null:
			charspr.set_modulate(speedcolor)
	elif (attpower):
		add_to_group("power")
		if charspr != null:
			charspr.set_modulate(powercolor)
#		add_to_group(priority)
	elif (attdefense):
		add_to_group("defense")
		if charspr != null:
			charspr.set_modulate(defensecolor)
#		add_to_group(priority)
	#MovePlayer
	var motion = vel * delta
	move(motion)
#	print(vel)
	#Slide player if colliding
	if is_colliding():
		var normal = get_collision_normal()
		motion = normal.slide(motion)
		vel = normal.slide(vel)
		move(motion)
		#Collision for hitbox
		#If the metadata comes back 0 it has not collided
		print(str(playercontroler)+" Collider's Metadata is: "+str(get_collider_metadata()))
		
		
		
		
	pass

Metadata is empty, but did you actually got them to collide? Is if is_colliding(): becoming true when that happens?

Zylann | 2017-04-25 18:15

Yes they are colliding, sorry I did not include that part in the statement.

lavaduder | 2017-04-26 07:51

:bust_in_silhouette: Reply From: Robster

You could try something like:

# Check if we have collided
		if(myCharacter.is_colliding()):			
			# Get node that we are colliding with
			var entity = myCharacter.get_collider()

… then do as you will with entity

note… this is when I’m using a specific class. Yours may look more like:

# Check if we have collided
		if is_colliding():			
			# Get node that we are colliding with
			var entity = get_collider()

I hope I understood you properly, if not just say.

Wait I can only get collision data from pacific entities? Is there a way to get collision data by a group of nodes.

I have two of these kinematicbodies set up, to collid with each other. And they are both from the same group, and instance scene. Is there a way to tell a collier with groups?

lavaduder | 2017-04-26 18:16

What get_collider returns is the node that collided, so if you put it on a group… just check its group^^ with entity.is_in_group("test") for example.

Zylann | 2017-04-26 19:33

I have tried using the is_in_group() function before. It failed, But I tried it again anyway and still got

Invalid call. NONEXISTENT FUNCTION ‘is_in_group’ in base ‘Nil’.

the function for some reason doesn’t exist in KinematicBody2D. I don’t get it. I’m upset. It’s really hard to make a game without basic collision.

lavaduder | 2017-04-27 08:07

“in base Nil” suggests that entity is null. The function exists in KinematicBody2D, it’s just that get_collider() gave you nothing. Which is unexpected ^^"

Zylann | 2017-04-27 19:48

I have no idea how to use this function. So I’ll show you what i’ve been using it as. Maybe you can tell me what I am doing wrong.

if is_colliding():
		#Collision for hitbox
		var entity = get_node("hitbox").get_collider()
		if entity.is_in_group("player"):
			entity.sethp(damage)
			print(entity.hp)
			pass
		else:
			print("no entity")

lavaduder | 2017-04-28 07:24

Wait… you are getting the collider from another node? I don’t know if it’s supposed to work (never tried this setup before), usually my script is on the KinematicBody/RigidBody directly and I use get_collider(), not get_node("hitbox").get_collider().
Also, what is the type of your hitbox node? I thought you had only two KinematicBodies?

Zylann | 2017-04-28 21:55

Hitbox is a CollisionShape node inside the KinematicBody. This has been changed some. Now it is a area2D node. Well a lot of things has changed

Here’s a complete tree
KinematicBody2D “Player”
-CollisionPolygon2D “colid”
-Area2D “area”
–CollisionShape2D “hitbox”

if is_colliding():
		#Collision for hitbox
		var entity = area.get_collider()
		if entity.is_in_group("player"):
			entity.sethp(damage)
			print(entity.hp)
			pass

If this does not help, then I’ll upload the project on github.

lavaduder | 2017-04-29 07:12

So if you use Area2D to detect the other’s Area2D, you could actually connect the area_enter signal on your Area2D instead of getting collider every frame:

func _ready():
	get_node("hitbox").connect("area_enter", self, "_on_area_enter_hitbox")

# Will be called once when another area collides
func _on_area_enter_hitbox(other_area):

	# Assuming your two objects have the same hierarchy you described,
	# you can get the other's root this way
	var other_kinematic = other_area.get_parent()

	# Do stuff

Zylann | 2017-04-29 16:13

My project is here.

https://github.com/lavaduderDev/G13-Fighter

I haven’t added the area collision to it though, this was upload before you responded.

lavaduder | 2017-04-29 23:54

:bust_in_silhouette: Reply From: lavaduder

Thank you Zylann for helping me out. I think I get it now.

In generic terms.
You should have the following 3 nodes
—body (anytype)
----------Area (2D or spatial)
----------------Collision (2D or spatial)
—collision (2D or spatial) #This is if you want the character to collide with stuff

while in gdscript

extends (What ever body type you have)

func _ready():
	get_node("Area").connect("area_enter", self, "_on_collision")
	pass
	
func _on_collision(value):
	collider = value.get_parent()
	#Then your else if ladder

Now In my case, as an example.
—Player (KinematicBody2D)
----------area (Area2D)
----------------hitbox (CollisionShape2D)
----------colid (CollisionPolygon2D)

extends KinematicBody2D

func _ready():
    	get_node("area").connect("area_enter", self, "_on_hitbox_collision")
    	pass
	
func _on_hitbox_collision(value):
	collider = value.get_parent()
	if (collider.is_in_group("speed")):
		pass #This is where My code should go if alternate  player is speed type
	elif (collider.is_in_group("power")):
		pass #This is where My code should go if alternate player is power type
	elif (collider.is_in_group("defense")):
		pass #This is where My code should go if alternate  player is defense type