I was making a melee weapon using a kinematic2d and collision shape in the front of it. The object just needs to rotate so far and then go to its former position, simulating it swinging around. I was thinking of using an area2d to recognize when it goes too far, and adjust its position for the swinging arch for different weapons. Thing is, the kinematic2d doesn't detect the area2d, nor does the area2d detect the kinematic.

I'm currently using this script for the rotating weapon extends KinematicBody2D


export var rotation_speed = PI


func _process(delta):
	rotation += rotation_speed * delta

and this one is for the area2d.

extends Area2D


func _on_WeaponStopper_area_entered(area):
	get_node("../Axe_Stone_Pivot").rotation = 0

Hi,

Is there any explicit need for usage physics system for that?

Isn't it possible to achieve the same easier by usage of lets say AnimationPlayer?

If you want different swing angles then instead of AnimationPlayer you can use Tween and just set appropirate start and end angle.

The physics would be mainly for the collider. I could try to make animations and use that (the weapon is only a single image), but then I still need the collision to be detected by enemies when they collide directly with the axe's blade, or missed if the enemy isn't in range.

I think your problem might be the special nature of KinematicBodies (not RigidBodies in kinematic mode):

  • They don't do collision detection unless you call collision detecting motion functions like move_and_slide()

From the documentation:

Kinematic bodies are special types of bodies that are meant to be user-controlled. They are not affected by physics at all; to other types of bodies, such as a character or a rigid body, these are the same as a static body. However, they have two main uses: ... Kinematic characters: KinematicBody also has an API for moving objects (the move_and_collide and move_and_slide methods) while performing collision tests. This makes them really useful to implement characters that collide against a world, but that don't require advanced physics.

https://docs.godotengine.org/en/stable/classes/class_kinematicbody.html

Areas will tell you if a body or other area intersects it, but it will not yield any information about the collision per se.

Bodies don't detect areas, areas detect bodies (default behavior) and other areas (when enabled)

Check your physics layers and masks. The area should be set up to detect the physics layer of the objects you want it to notify you of.

I know areas work on rigid-bodies in all modalities (kinematic, character, rigid-body and static), KinematicBody (2D) is a distinct subclass of PhysicsBody, so it may not be treated the same way as RigidBody.

If all else fails, as an experiment: Try attaching an area to the thing you want to detect and see your WeaponStopper area sees that after enabling the WeaponStopper to detect areas.

Also you might want to add collision exceptions to your area for your weapon to ensure that it is not interfering with the area. Also if your weapon is already intersecting the area, you might miss the enter event if you are connecting to receive the signals after it's been emitted.

Huh... guess I'll have to do some digging. The rigidbody2d keeps running from the player, most likely as it's effected by "gravity." As a top-down game, I don't want gravity to play a role, mainly just the collision detection, and perhaps later a push-back from an attack. The Area2d doesn't seem to notice another area, either. Thanks so far, though. This is insightful.

Don't forget you can lock each of the 6 axis (linear/rotation) on a rigid-body. Lock y to prevent it from falling.

Or set gravity scale to zero. ( I think this is the better option if you want other elements of the game to be effected by gravity).

I think you can also go into project settings to set overall gravity and you can elect to nerf it there.

Area's are supposed to detect enter/exit of bodies (by default and configurable) and areas (optionally). I know they work because I use areas all the time.

I would recommend a test where you set up an area you can walk your character into and work out any kinks in there. Again, make sure the Area has its collision mask set correctly to match the physics layer(s) of the objects you want detected.

All else failing, setup an example scene where you don't have areas detecting a body and post it here. Strip it down to the basics.

8 days later

Sorry it took so long. It appears as though nothing is detecting the axe, though the player is being detected by the area.

The new axe code:

extends RigidBody2D

export var rotation_speed = PI

var is_attacking = false

func _process(delta):
	
	if Input.is_action_pressed("Attack"):
		rotation += -rotation_speed * delta * 2
	if Input.is_action_just_released("Attack"):
		rotation = 0

I tested it using a simple area2D with a script to print "Hit" if it ever detects anything.

So, here is the axe. Nothing fancy, though this one is slightly different since it now only has its own rigidbody2d node for a pivot. I was trying to have it only detected when something hits the blade.

Here is the test object.


extends Area2D


func _on_Tree_Test_body_entered(body):
	print("Hit!")

The tree detects the player, a kinematic body2D, but it doesn't even detect the rigidbody2D when it is idling in the area2D.

Maybe the RigidBody2D is asleep and so the Area2D cannot see it? Maybe try setting can sleep on the axe to false, assuming its not already.

Okay, this is odd. It appears to be recognized now by the tree, but the weapon won't follow the player, and it won't rotate. I will keep digging.

Aha! Thanks, all!

I switched the rigidbody2d to an Area2D and set it so that it would detect the collision of the tree trunk (the collision shape under the static body2d). Same code, but I removed can_sleep, switched toextends Area2Dinstead of rigidbody2d, and added anon_body_enteredfunction on the axe. It now detects when it hits things and moves with the player. I don't have a better alternative at this point. I removed the stopper as it wasn't working. I wounder if I could use rotation to check if the swings are too long. I will keep digging.

I just got it how I would like the axe to swing. I will share the axe's code here in case someone could use it for their own projects. I set up my own timer to stop the swing after half a second. Thanks for the help!

extends Area2D

export var rotation_speed = PI

var is_attacking = false

var timer = 0
export var wait_time = 0.5
signal timeout
export var multiplier = 2


func _ready():
	pass

func _process(delta):
	
	if Input.is_action_pressed("Attack"):
		rotation += -rotation_speed * delta * multiplier
		timer += delta
		if timer > wait_time:
			timer = 0
			emit_signal("timeout")
		
		
	if Input.is_action_just_released("Attack"):
		_on_timeout()

func _on_timeout():
	#Your code
	rotation = 0

func _on_Axe_Stone_body_entered(body):
	if Input.is_action_pressed("Attack"):
		print("Hit!")


func _on_Axe_Stone_timeout():
	rotation = 0

2 years later