Hi, I was one of the main developers on the team for Rolantis.
We accomplished the swimming by reimplementing it entirely ourselves. For all of our animations, we had a walking and swimming variant. When the player was swimming, we should switch to our swimming animations instead of the walking ones.
We also made our own character controller to replace the default Roblox one. You can get the required information from the Humanoid object (mainly, the direction the player wants to be moving in).
When the player was in swim mode, we would activate a BodyVelocity inside of the character which completely controls the velocity of an assembly, ignoring gravity.
We used a spring solver to determine the player's current velocity in time, so as to smooth the player into full speed and back to rest when they press and release the movement keys. Tuning the spring's dampening gave the most convincing illusion of an underwater swimming effect.
Unfortunately, pulling something like this off is not simple. I wouldn't necessarily call it hard, but there's a lot of steps involved. To recap:
- Make two versions of every animation you want to play on your player, one for standing and one for swimming
- Rewrite animation controller to support standing and swimming state for all existing humanoid states, and play the correct one depending on the current state. Also implement a transition state between standing and swimming.
- Rewrite the character controller to also be aware of swimming vs. standing state, and when swimming use a BodyVelocity whose velocity is determined by a critically dampened spring. (We also combined the velocity of multiple springs to determine a final velocity, for things like water vents that would push the player in the water.)