Prevent jumping and gravity in water area without using a state machine

Godot Version

4.6.1 stable

Hello, I am working on a 2D game in Godot and I structured my project with several scripts:

  • GameCharacter (extends CharacterBody2D)

  • TopMovement

  • InputControllerBasis

  • InputController

The InputController emits a signal with a dictionary of inputs like:

{
 "Left": Input.is_action_pressed("Left"),
 "Right": Input.is_action_pressed("Right"),
 "Up": Input.is_action_pressed("Up"),
 "Down": Input.is_action_pressed("Down"),
 "Jump": Input.is_action_pressed("Jump")
}

The movement script receives this dictionary and applies velocity to the character.

My scene also contains a Sea area where I want different behavior.

Question 1

How can I make the character:

  • move normally

  • not be able to jump in the sea

  • not have gravity in the sea

I would like to implement this without using a state machine.

Question 2

I also want the character to print "shoot" in the console when pressing a shoot input only when on the ground, but not when inside the sea.

What is the best way to implement this behavior?

Should I use:

  • Area2D detection

  • collision layers

  • or another approach?

Any guidance or example would be very helpful.

Just out of curiosity but what’s wrong with a FSM?

fwiw, a state machine is a fluid concept. All it means is that your character is in certain states. When in those states, it can do certain things. If you implement this with a bunch of if statements, it’s still state machine, just one that’s probably hard to follow. But conceptually what you want is for your movement code to be aware of where the character is. So you would check, in your jump() function if the character is in the sea. Similar for gravity, if character is in sea: disable gravity.

Same for question 2. In your shoot function, check is_on_ground() and not in_sea()(the second is a custom function your write) and only shoot if both are true. As for how you detect if you are inside the sea… it really depends on how your game is structured. Use whatever makes the most sense.

3 Likes

Thanks for the helpful explanation.

The idea of making the movement logic context-aware clarified things for me. I added an in_sea flag using an Area2D signal and now conditionally disable gravity and jumping based on that, while also checking is_on_floor() for the shooting condition.

Everything works cleanly now. I appreciate the insight!