Ideas for swimming character

Hi guys,

Since a couple of weeks I’m working on a character control based on normen’s CharacterControl and I hit a wall. I need some new ideas, so if you have pointers, I would really appreciate it.

Basically what I have done with my character control is pretty basic: move around, crouch, jump, etc. But things get messed up when the character dives in the water. When the characters dives into the water, I set gravity to 0, the crouch button is used to swim down and jump button is used to swim up (basically I change the walk direction to go up or down and bypass the usual jump and crouch behavior).

I’m stuck at the point where the character needs to go out of the water. Initially, I test if the characters is near the surface (with a small margin) and if yes and if the character has a walkDirection that would let him out of the water, I block the vertical walk direction (so the character can’t swim out of the water). The problem with this approach is that when the character is heading toward a beach, (so the character control should be on the ground) it gets stuck on the beach and can’t go out. Walking out of the water should be ok, but not swimming out of it.

So I tried using the onGround() function, but the Character is considered on ground if it’s vertical velocity is 0. So when the character isn’t falling, it is considered on ground. Whenever the character swims, he is considered on the ground because he isn’t falling… not good since it doesn’t make the difference between walking out of water (ok) or swimming out of water (not ok).

So I tried to add a ghost control that would follow the character around, a small cylinder that would be under the character capsule to detect any collision and base my conditions to get out of the water on the collisions result. But strangely, this ghost control collides with the ground (TerrainGrid) even when far from it. I’ve seen other posts in the forum about this, but no real solutions or ideas to get this working. I also tried to make my own KinematicCharacterController to see how the capsule detects collision with the ground (after all, it works well there) but I can’t override key methods because of the Stack object. (I won’t go into details here) Anyway, long story short, I don’t understand how it is done in the KinematicCharacterController and how to replicate it for my ghost control…

But maybe I took a wrong approach right from the start. How would any of you approach this situation: swimming character control and transitionning between in and out of water?

Any pointers / ideas / suggestions would be very appreciated.

Thanks a lot! :slight_smile:

I don’t use character control so there might be some easier way but one way to check the height over the terrain is to make a ray test, I do it in a physics tick listener but that might not be necessary.

Something like this:

RAYTEST_LENGTH is just some constant I use since I’m not interested in height above a certain value.


List<PhysicsRayTestResult> results = new ArrayList<>();

this.physicsSpace.rayTest(from, to, results);

float height = RAYTEST_LENGTH;

for (PhysicsRayTestResult result : results) {

int collisionGroup = result.getCollisionObject().getCollisionGroup();

if ( check that you intersect the terrain and nothing uninteresting like the player itself ) {

float intersection = result.getHitFraction() * RAYTEST_LENGTH;

height = Math.min(height, intersection);




1 Like

@jmaasing: It’s a good idea! I should have thought of that. Thanks a lot! :slight_smile:

@jmaasing: It works great with the ray test. I make 4 ray test rather than a single one because if the slope has a great angle, then making a ray test at the center of the character control doesn’t always hit the ground. But with 4 ray tests, it works great! I will most certainly reuse this trick

Thanks again! :slight_smile:

Happy I could help. I use that myself for lots of things, for example I do almost the same as you do but that is to let my hovercraft follow the terrain slope - so I recognized the problem :slight_smile: I haven’t measured but I’ve heard it is a pretty fast ray test also.