@lazy_turtle said:
Hey everybody,
I'm working on a project in which I am using the function move_and_slide to move around my character (kinematic body 2d). This character is built of many parts - its legs, arms, head. I've instanced in these parts into a player scene.
The issue I'm having is that, because I am using move_and_slide, whenever I put a collision shape as the child of a sprite, the collision object no longer works. The order below is a workaround for the problem, but it would be nice to find a better way to organize it.
Unfortunately, I do not know of any way to get around this. Godot's collision nodes look for collision shapes as direct children of the node. One way you could get around it for usability is to write a script that copies over the collision data from deeper instanced collision shapes and makes new collision shapes as direct children of the node, but I'm not sure the effort would be worth it (nor how it would effect performance).
The main issue, however, is with detecting collisions. My game is a 2d fighting game, and I want each player to take damage whenever they get attacked by an opponent.
I can't find a signal like on_area_entered for kinematic_body 2d, the sprite, or the collision shape. Therefore I created an area 2d with new collision shapes that are basically just replicas of the other collision shapes. From there I am able to use on_area_entered. This is still very inconvenient because I end up using two collision shapes instead of one. Are there any fixes to this problem?
Sadly, there doesn't appear to be anyway to detect a collision with a KinematicBody2D node like you can with Area2D nodes.
There are some options you could look into, though I have no idea which would be best, nor if they would work (in theory they should though!)
One thing you could do is use a RigidBody2D node instead of a KinematicBody2D node. This would require changing any KinematicBody2D specific code, unfortunately move_and_slide
is not a RigidBody2D function, but the change to a RigidBody2D node would allow you to use body_entered
and body_exited
signals and/or the get_colliding_bodies
function (documentation).
Unfortunately, other than that I do not know of any way to remove the Area2D
node entirely. However, you can reduce some of the manual work needed to copy the collision shapes and position them by writing a helper function to do it for you. Something like this (untested):
# Add this to the Player1 node!
func copy_shapes_to_area(area_node, shapes):
# This function will copy all of the collision shapes in the
# 'shapes' variable (a list) and will add them as children
# to the passed in area node, 'area_node'.
for copy_shape in shapes:
var new_shape = copy_shape.duplicate()
new_shape.global_position = copy_shape.global_position
new_shape.global_rotation = copy_shape.global_rotation
new_shape.name = copy_shape.name + "_COPY"
area_node.add_child(new_shape)
# Then you can use it like this:
func _ready():
copy_shapes_to_area(get_node("PunchForearmArea"), [get_node("ForeArmCollision")]
copy_shapes_to_area(get_node("KickArea"), [get_node("RightLegAreaCollision")]
copy_shapes_to_area(get_node("HeadButtArea"), [get_node("HeadCollisionShape")]
# Then you can also add multiple shapes if needed. For example:
"""
copy_shapes_to_area(get_node("HeadButtArea"),
[get_node("ForeheadCollisionShape"),
get_node("ChinCollisionShape"),
get_node("HairCollisionShape")])
"""
Then you wouldn't need to make the duplicates within the scene, as the script would do it for you. That might make it a little easier to manage the collision shapes, as keeping them in sync (both in position and shape) would be handled by the script (since it duplicates the shape).
Hopefully this helps!
Side note: Welcome to the forums!