How to detect that camera is not falling?

Hi all,

Found a bug in one of my previous demos: https://www.babylonjs-playground.com/#3CPL8T#1
If we will click spacebar quickly the avatar will jump higher and higher. This happens because I drop this.jumping flag on key up event. See line 135.

Actually I need to drop it when camera will be on the ground. One obvious solution is to check inside of onCollide event if collided mesh is a “ground” and then drop the flag. But it’s not universal. What if I land on any other mesh that actually is not a “ground”? Is there a way to check that camera has stopped falling?

Hi @splash27,
I think I had a similar issue with player camera falling off of a building. I found some suggestion about using a ray that points to -Y, and then check the distance with the first picked mesh (or you can set the length of the ray when you define it). I used and it works perfectly.
Hope this helps.
Abdullah.

@Abdullah_Alkawatrah,
Thank you!

But how did you cast the ray?

Did you cast a new ray each time inside onCollide event or when camera moves?
Or did you create a ray once and change only it’s origin inside onCollide event or when camera moves?
Or did you find a way to set camera as “parent” for ray?

I am just looking for the most optimized solution.

I am not sure if the below is clear enough. I call this in the renderloop. I found using a dummy box hidden below the camera (bottomBox) as the origin of the ray easier to implement. The dummy box is updated with the camera position to create a new ray.
This will actually check if the camera (bottombox) is above and in contact with any mesh.

castRay() {
var origin = this.bottomBox.position;
var forward = new BABYLON.Vector3(0, -1, 0);
forward = this.vecToLocal(forward);
var direction = forward.subtract(origin);
direction = BABYLON.Vector3.Normalize(direction);
var length = 30;
var ray = new BABYLON.Ray(origin, direction, length);
var hit = this.scene.pickWithRay(ray, (mesh) => {
if (mesh.name != “bottomBox”)
return true;
return false;
});
if (hit.pickedMesh) {
// console.log(hit.pickedMesh.name);
this.canJump = true;
}
else {
this.canJump = false;
}
}

@Abdullah_Alkawatrah, your solution is interesting, but it still doesn’t work good for me.
https://www.babylonjs-playground.com/#WECN4N

Problem 1:
Actor jumps now only when I release button. Not on keydown as it was before.
I had to add additional flag check (jumpBtnPressed at line 229) to fix that. But I feel that this is wrong. One flag should be enough. Probably problem is somewhere else in my code.

Problem 2: If I will be quick enough, I still can do at least double-jump. Despite I set length of the ray very carefully and the jump animation takes only 20 frames.

I afraid that there might be some kind of race condition between checkInputs call and onBeforeRenderObservable call inside of BABYLON. Not sure though.

@splash27, i am using event listeners not camera controls. I am not sure if this makes a difference, I think camera inputs are queued for processing.
I am using this here: https://csserver.herokuapp.com/. You can try to climb the ladder and see how you cannot jump midair. Use shift to jump. If you look (point camera to player foots) far down you will see the dummy box, which i think can be removed (I have seen in your playground you are using camera position instead).

@splash27, I found where i got the concept of using ray cast to detect if camera is on top of something.

1 Like

Well, the only possible solution I found to suppress undesired double jumps is throttling of jump button presses.

https://www.babylonjs-playground.com/#WECN4N#1

Hi guys!

Recently, I did another playground that used simple ray-casting… so now I’m an expert. (not) :slight_smile:

Splash, take a look at https://www.babylonjs-playground.com/#WECN4N#3 - lines 118-130 area. (I changed all ‘this’ to be ‘camera’… maybe wiser in this situation). :slight_smile:

I also changed jump height from 6, to 16… just to help me test stuff.

Um, I don’t use a target… to derive a direction for the raycast. I just force the direction to be BABYLON.Vector3.Down(). I KNOW your player/cam is around 4.02 above the ground (and same distance above anything the camera/player jumps-onto).

The ‘hit’ object that is returned by the raycast… contains a .distance which we can use. You can watch line 128 @ console… and see that cam never gets higher than 20, so I made my raycast length be 30… long enough to HIT floor even when cam/player is at top of jump-height.

The raycast is not a performance issue, because we just do ONE cast at the beginning of a jump attempt.

Wha-da-ya-think? No more lines 106-109 hassles, eh? (flags-o-many) Abdullah had a pretty good idea, and we just needed to wire it into your system… and see if it works. Once we removed the need for a target, and instead, aimed the raycast straight down below the camera… it became more useful to us.

There MAY BE problems ahead yet (for your app), but maybe not. Perhaps this camera “butt-cast” will work good for ya.

I see, in BUGS… that you are beginning the problems of WHO IS BOSS… physicsImpostor… or animation keys. Maybe keyframe-animating physics objects worked in 3.0, but that is not good. technically, it should never work… as the impostor is the boss of the mesh… and impostors ONLY move when given a physics-approved force. Keyframes… setting non-physics properties… are not a physics-approved force. :slight_smile: Here’s your “k-jumper” playground… but using a physics-approved force in line 57.

Perhaps a smarter way… end the keyframe mesh-animation… with mesh positioned a tiny distance above floor… and right there… either by animation onEnd callback or by an animation event… add the impostor RIGHT THEN. Always remove the impostor before the keyframe animation starts… and always add it again, just after anim ends. That’s more proper, I think.

Possibly soon… you will be talking about camera/player being TOTALLY controlled-by physics forces. I think @givo and someone else… went down that trail… within the last year… and they both went insane. hah. (mostly from trying to keep camera from sliding (downhill) when player stops on inclines)

I hope I have been helpful. Party on!

Hi Wingnut,

Your solution looks much simpler and it solves double-jump problem, but it is kind of buggy in some other places.

  1. If you will press and hold spacebar until jumping end and then release it you will jump again. That’s weird.
  2. If you will press and hold spacebar until jumping end and then will press movement button you will jump.

I am not a binary flag maniac, but I had to use them to suppress all this strange glitches.

this is ok inside keyboardHandler function. Look how I am setting an observer:
keyboardObserver = scene.onKeyboardObservable.add(keyboardHandler.bind(camera));

Maybe it makes my playground a little bit more complex, but it makes a copying from my codebase easier, because I am actually extending FreeCamera by adding my methods.

1 Like

Yep, that was me. Topic was called SSS (stop sliding on slopes)

I’ve taken a break from coding for the summer, but soon I’m gonna push myself to start making NYNS for real. I’ll steam it at twitch.tv/GivoGames so I can’t watch youtube if I get frustrated.

1 Like