I’m porting my developing -but fully functional- project from 3.5 to 4.2.1 but I’m getting trouble with some unexpected $AnimationPlayer behavior. It’s a 2D fighting game. There are strike animations that draw a CollisionShape2D called HitBox. That shapes usually last between 2 and 6 frames, who Is called “active time” in frame data. If a HitBox meets a rival HurtBox, the HitBox is disabled via code, the animations are freezed for a instant, the hurt animations called and then everything is unpaused. The problem is that in Godot 4.2.1, after the pause, the AnimationPlayer reenables the disabled HitBox, what it causes undesired rehits. Everything works superb in 3.5 and the HitBox is disabled by default. It seems that the difference is tha 3.5 only refreshes the Hitbox state in keyframes, while 4.2.1 actives again the HitBox if the Timeline is between the “disable” and the “enable”. Update mode is set in “discrete” and interpolation in “linear” in both versions.That is a huge problem for me, specially in animations where the HitBox must be enabled and disabled multiple times (i.e. Honda Hand Slaps like especials). I can’t find none to change this behavior. Maybe a bug or I’m missing something?
it could be your collision2d hitbox’s disabled property is not actually disabled on first frame when it’s supposed to be turned off. i read from this disabling collisionshape has weird results said need to set_deffered() in godot 3 tho.
how about making the entire collision visible to true then false?
Hi friend. The HitBox is disabled twice by code and in the inspector too by default. No need to disable it in frame 0, but I tryed too just in case. In fact, the HitBox starts disabled, what is fine. The problem comes when I pause() the $AnimationPlayer, wait a small time, and play() again. Then, the disabled HitBox is enabled again and what doesn’t work this way in 3.5.
Thank you anyway for the reply. Still figuring out…
Hi again. I made some testing in a test project with only two CollisionShapes. One has active frames of visibility and the other active frames of being enabled. The results are the same. If I pause() the animation, disable and make invisible the shapes, and then play(), each area return to be enabled or visible in each case. As I suspected, Godot 4 AnimationPlayer doesnt wait to the next keyframe with state changes to alter the properties, what it does is triggering again everything in the zone between one property and another. One little difference is that in Godot 3.5 the animation is stopped via stop(“true”) but this command has a different behavior in Godot 4.2.1 and pause() needs to be used instead. Ah, of course I’m using the deferred call.
Seriusly, I think this is either a bug or an undesired side effect, because I didn’t read anything about such changes in the changelogs. Its terrible because makes near inviable my game without a masive investion of time and It works like It should be in 3.5. Maybe should I report about this?
from what i read, the only difference of “pause” for godot 3.5 and godot 4.2.1 is the syntax to pause
for godot 3.5: anim_player.stop(false)
for godot 4.2.1: anim_player.pause()
I simply disable the HitBox with: $HitBoxes/HitBox1.set_deferred("disabled", true)
Pause the animation with: $AnimationPlayer.pause()
Wait a short timer for adding more impact effect (I call it “Hit_freeze”) for about 0.15 seconds.
And then: $AnimationPlayer.start()
In this moment, the HitBox is enabled again. I did a simple project to show this, but is easy to do by yourself. Simply do an animation to enable a CollisionShape2D for a few seconds, pause the animation, disable the CollisionShape and unpause the animation to see what happens.
Mmm the demo was intended to make at the same time:
In frame 29:
HitBox1 → Enabled
HitBox2 → Visible
In frame 81:
HitBox1 → Disabled
HitBox2 → Invisible
Setting the easing in “continuous” makes the AnimationPlayer do some interpolation between the ON and the OFF frames losing all the precission needed. Look how after your adjustment the two shapes aren’t sincronyzed. That’s why “continuous” is not appropiate for ON/OFF values like these, when do not want any interpolation. I think its because that interpolation the HiBox2 doesn’t return to visible state inmediately after unpause. Because the 81 frame it’s near and the AnimationPlayer is calculating that it’s time to set it to invisible too.
Ah, it’s a GIF the video you embedded in your post? That’s useful. I need to learn how to make it. Thanks for your efforts and atention too.
No, continuous its not right for ON OFF parameters, those who only have to be 100% or 0%. If you chose “Continuous” in such values, the AnimationPlayer makes a line between the ON and the off keyframes and calculates where to change to value depending on the easing. By default, just in the middle of the two keyframes. That “Continuous” option is indeed for transitions like movements, scales and such…
Of course I need precise control of the HitBoxes. In a fighting game, the difference between 3 and 6 active frames is huge, for example. Of course I can do some coding to overcome this problem, but this was working perfect in 3.5 and I’m now pretty sure this is a undesired effect unnoticed by the developers.
Ah, thanks for told me about the ScreenToGif. It will be very useful to me.
Did you overcome this? I am having the same issue in Godot 4.2.2, Tried with disabling collision shape in the keyframes, also with monitor/monitorable but it keep always turned on or off… I only want to enable in some keyframes
Unfortunately, no. It’s for this little issue I’m sticking with the 3.5 version. Maybe we need to report this to the developing team because, from my point of view, It’s a bug.
Tryed the new 4.3 version. This issue has gone! Now, I’m a little closer to porting my game to Godot 4. I’m still around 5 or 6 years far from ending it, so I believe that its better to jump to the latest version. Specially, due to the AnimationPlayer improvement.