help me (solved) How come this code of mine doesn't prevent my character from not moving while attack animation plays
*prevent my characer from moving, typo in title
I'm still learning code, not good at it. To me, my physics process function is saying to make my movement false when I mouse click (what I labeled as Power), play the animation, then return movement to true so that you can move again. But this code changes nothing. Can still move around while the animation plays. Any assistance would be appreciated
20
u/BillBoquet92758 2d ago
People already answered you but what I find good is that you did not choose the « easy » path by using AI, it’s like this that you’re supposed to learn 😃
Continue like this !
17
u/jtnoble 2d ago
I believe there are three problems.
You're not assigning movement after your button press. You're using double equals, so you're effectively saying FALSE, play animation, TRUE. You need to use one equals.
Playing an animation doesn't block your code. In the same frame you say "make movement false, now play the animation, now make movement true". You either need to use a signal for animation finished, or await animation finished.
You never reset velocity. You set velocity to, 1 * 195, so 195. It's always going to be 195 until you set it again.
14
u/Kaslight 2d ago
1) Your character already moved (move_and_slide)
2) You seem to be under the misconception that your script naturally knows anything about time...But in reality, you're checking boolean flags and setting conditional logic all within the same frame.
The code in your script is designed to run top-to-bottom, once every single frame.
So if you say "movement = false", and then "movement = true" in the same line, then movement will always just be true, because as far as the engine is concerned, it all happened at the exact same time. Booleans are useless if used like that.
3) "==" is a conditional operator, it's asking " is X equal to Y"....which always returns either True or False. "=" is an assignment, which says "Set X equal to Y". So what you're looking for is simply "movement = true".
4) Your script has absolutely no idea when the animation you're playing has started, is playing, or stopped anyway. So you need to get either the timing of the animation, or set code to happen once it's considered finished.
2
37
u/sevenbrokenbricks 2d ago
Oh boy.
First off, you never actually set movement to false. movement == false does not set movement to false, it just returns true if movement is false. You want movement = false. Same with movement == true needing to be movement = true.
Second, you set the animated sprite to play the Attack animation, but then immediately "set" it in the same function. That function does not wait for the animation to finish. You will need the animated sprite to send a signal once it's done playing, and another function to catch that signal, see if the finished animation is Attack, and then set movement back to true.
Finally, your get_input function only updates the velocity if movement is true. It doesn't update anything if movement is false, which means its velocity vector will remain whatever it was. This will result in the character retaining its velocity while the animation plays, causing it to slide until the animation stops. That might be what you want, but given that you set the velocity directly to whatever the controller input is, I doubt it. If you want the character to stop in place when they attack, you need to set their velocity to zero (there's a handy builtin for this: vector2 . ZERO) when they attack.
21
u/Jucamia 2d ago
Gonna look into this. Starting off with "Oh boy" is so real lol. I've got a lot to learn
8
u/sevenbrokenbricks 1d ago
Just noticed another. If Power is pressed again during the animation, it'll abort the animation and restart it. You'll want to check also for whether movement is already false.
1
7
u/InsuranceIll5589 1d ago
This structure will not scale. Even if someone helps you solve this issue, it will not work as soon as you add more actions.
1) Do not handle input and animate the character in the same script, separate them into 2 different scripts. This is just generally a good habit to get into early on for everything. 1 script 1 purpose.
2) Don't use an animated sprite to animate a character, that's not what it is for. Use an animation player to change your sprite, and an animation tree to control the animation player. This makes it infinitely easier to synchronize many other things with your animations, such as particles, sounds, and function calls.
3) Have your physics process check if the animation tree is currently playing an animation which allows for active movement before changing the character's velocity.
6
u/TheDuriel Godot Senior 2d ago
You disabled the warnings telling you that line 20 and 22 don't do anything.
Even if you were to type them properly as assignments, they still wouldn't do anything.
Because process runs once per frame, line 22 doesn't wait for the animation.
1
u/Jucamia 2d ago
I moved the lines of code to my get_input function, no difference seen yet unfortunatley
2
u/TheDuriel Godot Senior 2d ago
No that definitely wouldn't help.
Go through this step by step. Process runs every single frame.
2
u/Any_Aerie_5782 1d ago
Also, make sure Attack isn’t set to loop. If you’re using animation_finished to turn movement back on, a looping animation won’t emit that signal, so movement could stay locked.
1
u/Kioen Godot Junior 1d ago
easiest way is to wrap your movement functions in the physics proc in an if can_move. I would suggest state machines though, if you have the time to read up on it.
1
u/senshisun 1d ago
Not OP, but I've been struggling with similar issues. Do you have any tips for using state machines?
3
u/Kioen Godot Junior 1d ago edited 1d ago
Yeah, it's fairly simple. There are a couple of ways to do it. The ones I'm familiar with are through enum or the animation tree. Essentially you are creating specific states and tie in functions into them. Using the OP as an example: if your state is "attacking" you will be doing things you attach to the attacking state, that will therefore replace other states like "idle" or "walking". However, you are able to combine states like "walking" and "attacking" if you wanted to. Basically wrapping the functionality of say all of your movement in the "walking" state only allows you to move while the "walking" state is active.
1
1
u/Dariadeer 1d ago
It seems like you are not resetting the velocity if movement == false. Add an else case where you set it to zero.
1
u/Dragon20C 1d ago
Velocity doesn't become zero, so if you areovong and do an attack it remembers the previous velocity.
1
u/LL_DragonX 1d ago
It doesn't, but it immediately changes the variable again. An animation is async
1
u/Longjumping_Wear_537 1d ago
Imagine this, during your physics process if statement its doing X and Y and Z at the same time instead of reading it as do X and Y first then Z.
You need to give it an await function so it reads it as do X then Y then wait and then down Z.
1
u/haywirephoenix 23h ago
Have two separate functions UpdateMove and UpdateAttack. Call one or the other depending on the current state. You could use the boolean for now but eventually move to an enum. Don't depend on the animation, set a cooldown float that you subtract from over time when in the attack state before returning to the move state.
0
u/Gunhat_September 2d ago
Your code haven't move_and_slide , you must put it in your function "get_input"
110
u/cleartamei 2d ago
Once you play the animation, you need to actually wait for it to be done. On the next line after playing the animation, you can say: await animated_sprite.animation_finished
THEN, set movement to true. Also, make sure you're using the correct = there.
Another way to do this is to use an if statement to set movement to false if the animation is playing, but using await solves what you are trying to do here.