I've always just used a Area2D that has a body_entered and body_exited signal that tells the entity that it is underwater. Then I use a few conditions that check if the entity is underwater, and if it is, I make gravity less, apply movement dampening, and other minor changes that make it act like its underwater.
It is a tad harder to maintain though, especially depending on the complexity of the code. There are probably better ways to do it.