Attention | Topic was automatically imported from the old Question2Answer platform. | |
Asked By | OiKeTTLe |
As the title suggests, in my project, I’m using two booleans, one when the weapon is inside the enemy, and another for if the attack animation is active. If both are active, then I can damage the enemy. The issue I’m encountering is that the weapon only damages the enemy when the hilt (the origin of the area 2d) is touching it. When the blade, which is a part of the same collision shape, touches the enemy, nothing happens. In the image attached, I’ve set up strings for testing. I attacked away from the enemy twice, twice when I attacked the enemy with the blade, and another two for when I attacked the enemy up close with the hilt. It clearly shows that when the blade touches the enemy, both conditions are met, but it doesn’t trigger for some reason. Any help would be appreciated! Attached is the code I’m using and the results below it.
Link to the image if the embed doesnt work asjda hosted at ImgBB — ImgBB
The code isn’t showing…
Snail0259 | 2021-07-14 10:48
Added a link to the image, sorry.
OiKeTTLe | 2021-07-14 10:51
Images don’t load properly from that website here, but we can follow the image link anyway so I have seen your code.
I don’t think there’s anything wrong with it.
But could you show an image of the collision shapes in-game?
Select (top menu): Debug > Visible Collision Shapes, which will show the outlines of the shapes while running your project.
Does the sword collision shape intersect the enemy?
What might be happening is that while you have the sword animated(?) the collision shape isn’t and thus stays near the player.
Yuminous | 2021-07-14 10:52
Here’s a video: 2021-07-14 20-57-21
OiKeTTLe | 2021-07-14 10:58
Okay, so I can see the hilt seems to a separate collision shape and that’s the one actually getting checked which is where your problem is (since the attacks only work when it intersects).
But that seems strange if they are meant to be the same collision shape… could you show your node tree?
Yuminous | 2021-07-14 11:03
Link - amsnda hosted at ImgBB — ImgBB
OiKeTTLe | 2021-07-14 11:18
It’s as you say.
Hm… I feel like what’s happening here is that the sword isn’t checking for collisions while it’s being animated (so only when it reaches the idle position does it actually ‘collide’). Unfortunately I don’t know the answer here without being able to play with the whole project, but you can test this — offset the collision shape so it is facing forward by default.
You don’t have to change the animation, just rotate the sword collision to the front and facing slightly down (to test if the animation affects anything)
This isn’t the solution, but does that make it work?
Yuminous | 2021-07-14 11:38
No, unfortunately not. The collisions are still detected through the animation, but no damage is received.
OiKeTTLe | 2021-07-14 11:51
Okay, that is a head scratcher. I’ve wrote many similar statements and never had any issues like that.
If you remove is_attacking == true
and only check if is_in_body == true:
, then…?
Yuminous | 2021-07-14 12:11
Why not add your code into the question using the code block or tripple backtick ```
clemens.tolboom | 2021-07-14 12:12
Same thing happens again. I’ve come to the realisation that it works properly when the sword doesn’t leave the enemy’s body at the end of the animation; this was achieved by have the blade horizontally jab forwards when attacking the enemy. This issue is resolved by moving the code from under the attack command into the _physics process directly, but this causes the damage to be dealt every frame, which I don’t want. I can’t tell if the issue is with the overlap, or with the attack command. Also, the code block doesn’t wanna work. Here’s the full script for the sword:
extends Area2D
var is_in_body = false
var is_attacking = false
var can_attack = true
onready var swingtimer = $Timer
onready var attacktimer = $Timer2
func _on_Sword_body_entered(body):
if body.name == “PlayerTwo”:
is_in_body = true
print(str(is_in_body, “inbody”))
func _physics_process(delta):
if Input.is_action_just_pressed(“attack”) and can_attack == true:
$AnimationPlayer.play(“swing”)
can_attack = false
attacktimer.start()
swingtimer.start()
if $AnimationPlayer.current_animation == “swing”:
is_attacking = true
print(str(is_attacking, “attacking”))
if is_attacking == true and is_in_body == true:
print(“attacksuccessful”)
get_node(“/root/TestLevel/CanvasLayer/FightUI/Player2Health”).value -= 20
func _on_Timer_timeout():
is_attacking = false
$AnimationPlayer.stop()
func _on_Sword_body_exited(body):
if body.name == “PlayerTwo”:
is_in_body = false
func _on_Timer2_timeout():
can_attack = true
OiKeTTLe | 2021-07-14 12:31
There’s only really one thing it can be according to the code:
func onSwordbodyexited(body):
if body.name == "PlayerTwo":
isinbody = false
Right here, this function is being called before the next _physics_process
frame and is setting the isinbody
bool to false
before the if
statement can check it. The animation and this function are running at a higher framerate than _physics_process
, which is why the issue is present when the animation is running normally but then goes away when the sword doesn’t leave the enemy’s body. Probably.
Yuminous | 2021-07-14 12:37
Damn, thanks for spotting that. How can I delay this enough to allow the damage to take place, while still setting the bool to false?
OiKeTTLe | 2021-07-14 12:39
Since nothing here really needs to be bound by delta, try change _physics_process
to _process
and see if that fixes it
Yuminous | 2021-07-14 12:41
Didn’t fix it.
OiKeTTLe | 2021-07-14 12:46
…And commenting out that function?
It would be nice to at least verify if that’s the problem or not.
(also to help yourself with diagnostics put another print
function for print(is_in_body)
right before the if
)
Yuminous | 2021-07-14 12:52
Here are the results from your suggestion (you seem to have been right):
Attacking away from the enemy:
Trueattacking
Falseinbodybefore
Attacking the enemy, but not right up against them:
Trueattacking
Falseinbodybefore
Trueinbody
Landing a successful hit:
Trueinbody
Trueattacking
Trueinbodybefore
attacksuccessful
Here’s the updated function:
func _process(delta):
if Input.is_action_just_pressed(“attack”) and can_attack == true:
$AnimationPlayer.play(“swing”)
can_attack = false
attacktimer.start()
swingtimer.start()
if $AnimationPlayer.current_animation == “swing”:
is_attacking = true
print(str(is_attacking, “attacking”))
print(str(is_in_body, “inbodybefore”))
if is_attacking == true and is_in_body == true:
print(“attacksuccessful”)
get_node(“/root/TestLevel/CanvasLayer/FightUI/Player2Health”).value -= 20
OiKeTTLe | 2021-07-14 12:59
I mean, I think I would have just given up if that didn’t fix it. Haha.
Okay, so… couldn’t you just put the is_in_body = false
in the on_Timer_timeout():
function?
Yuminous | 2021-07-14 13:06
It was a good idea, but it didn’t work. I’m not sure what to do anymore Thanks for the help, and for your time, I really appreciate it
OiKeTTLe | 2021-07-14 13:09
But like, the more it doesn’t work, the more I’m intrigued how it’s possible that it doesn’t work and then more interested I get.
But I think I might have overlooked something pretty major as well:
All of this is all contained within is_action_just_pressed
and the code won’t (re)evaluate unless the action is just pressed.
Thus: try mashing the attack button really fast: does it…?
And one more thing if you decide to come back to this: put is_in_body = false
inside of the if is_attacking == true and is_in_body == true:
and delete that other function.
Good luck!
Yuminous | 2021-07-14 13:19
You’re an absolute genius; putting the is_in_body = false functioning inside the if statement worked! I can’t believe I didn’t think of that. Thank you so much for your help and advice, it was really helpful. Can’t thank you enough.
OiKeTTLe | 2021-07-14 13:29
Haha… I don’t know about genius… it took me this much just to debug < 40 lines of code with you. But I’m really really glad you got it working! I’ll simplify this thread into an answer so the question can be seen as solved.
Yuminous | 2021-07-14 13:33
Great, thanks.
OiKeTTLe | 2021-07-14 13:35