I've done a few of these questions for a couple projects, so I might be able to help a bit
1) Switch to swim control mode
This one depends a bit on level design and how you want water to function. The simplest way is to have a water plane that is at a certain height and if the player goes below this height, water mode is activated. This is a very cheap and easy way to know when a player is underwater (and needs swim controls) or whether they are above the surface. Likewise, you can tell if the player is on the surface by seeing if it's within a close range from this Y position.
However, that method is also a tad limiting in terms of level design, as you have to make sure all your non-water areas are above the Y position and you cannot have pools of water elsewhere. The other way I've done it is to have an Area node and the on_body_entered
and on_body_exited
(I think that's what they are called) signals to inform the bodies that they have entered/exited a water area. Something like this, for example:
func _ready():
connect("on_body_entered", self, "on_body_entered")
connect("on_body_exited", self, "on_body_exited")
func on_body_entered(body):
if "is_in_water" in body:
body.is_in_water = true
func on_body_exited(body):
if "is_in_water" in body:
body.is_in_water = false
The downside of this method is you cannot really have overlapping water areas, but compared to the other method (Y-plane), it's much more flexible.
2) Floating on water ( no need to based on shader, just faking floating up and down)
The way I did this was to invert gravity so the player floats up when they are underwater. I didn't program anything for floating on the surface of the water, however I did get some floating like behavior as the gravity switched from being inverted to normal as the player broke the surface of the water.
If you want to have just general floating, without necessarily moving the player all the way to the surface, what I can see doing that might work is simply switching the gravity direction from DOWN to UP on a timer when the player is underwater, so they float a little up and then float a little down.
3) A button to propel forward (swim and underwater)
This should be similar to normal movement, I think. I haven't really done this beyond swimming on the surface, in which case I just used my normal ground-based movement code and it worked fine.
4) Slowly sinking down or floating up depends on where you at under water
Not totally sure on this one, but I think it's similar to number 2.
5) Underwater effect under the surface
What I did for my game was attach a RigidBody to the Camera node for the sole purpose of detecting if it's underwater (similar to answer 1) and if it was, I changed the visibility of a TextureRect that had a simple shader that applied slight distortion and color tinting to the screen so it appeared the player was underwater. There's probably better ways to handle it, but it worked decently for my use (though the player wasn't really intended to be underwater for more than a few seconds in that game so... yeah)
Hopefully this helps a bit! This is just how I approached these questions when I was making something similar, but there are many, many different ways to handle this type of thing. :smile: