How to detect avatar is on the ground?

I have an avatar walking around a city. The city is one big mesh with uneven surfaces (road, curb, pile of dirt, etc…)
I’ve enabled collisions and have defined an ellipsoid for my avatar so when she walks she’ll always be on the surface. My avatar can also jump and fly. I’m trying to detect when the avatar is on the ground so I can play the walking animation.
I’ve tried checking avatar.intersectMesh(city, false) but its always false. Probably 'cos one mesh isn’t going through the other mesh.
I tried playing with physics imposters using the Cannon engine and that turns into a whole ball of mess that I’d rather avoid (I think it only works with spheres).
So is there a simpler way of checking that my avatar is on the ground?

not simple way but maybe a possible way
let me check it

1 Like

Why not using mesh.moveWithCollisions?
https://doc.babylonjs.com/babylon101/cameras,_mesh_collisions_and_gravity#next-step

I am using mesh.movewithCollisions. But I’m trying to figure out programmatically when the avatar has collided with the ground so I can change avatar animation to walking

for example, in this demo https://www.babylonjs-playground.com/#4HUQQ#353 how can I trigger an event when the box has collided with the ground? Bare in mind, my real situation is using mesh against mesh instead of primitive shapes

If you have an ellipsoid defined for your character collisions anyway, then you can probably do a Ray Cast from the ellipsoid absolute center in the direction of the gravity vector (probably your negative Y world vector). For your Ray Cast try to include only meshes that you want to act as walk-able ground. If the distance is about your ellipsoid’s height / 2 plus some error margin then your avatar is very close to a ground. If your character can also crouch then adjust the distance to look for according to the ellipsoid radius when casting into in the gravity direction.

https://doc.babylonjs.com/babylon101/raycasts

1 Like

Thank you. That technique worked for me. I used something like this https://www.babylonjs-playground.com/#4HUQQ#358

1 Like

so you dont need any New :smiley:

I’m still refining the code. I’m raycasting from the centre but its not accurate because my avatar has a larger surface area. You can see in the image. I need to raycast from an area not a point.

This video demonstrates the problem of casting a ray from a single point. The textbox shows the distance from the middle of the avatar to the ground. On a flat surface its pretty close to 2.02 but walking up steep items, like the car wreckage, the front of the avatar goes up first but the raycast will compare the middle which will still be hitting the ground instead of the car so the distance can jump to 3.8. That’s too inaccurate.

Maybe I need to do raycasting for all 4 corners. Hopefully that won’t reduce frame rate much.

1 Like

Hi guys…
If I may butt-in… Babylon.js Documentation (groundMesh)

There are two funcs (likely raycasters)… getDistanceToCamera() and getHeightAtCoordinates()… both likely helpful in certain situations.

But yeah, those “coordinates” might need to be the boundingBox corners. ie. player.position.clone().add(new BABYLON.Vector3(player.getBoundingInfo.boundingBox.extendsWhateverX, extendsY, extendsZ)) … one for each bottom corner. Erf.

Anyway, I just wanted to remind of the two functions available on groundMesh. Party on!

I did some tests. It appears that I also need to raycast going straight up, 'cos in some areas my avatar bounding box is going through the ground so the ground is already above. I tested by walking up a car then walking off it.

From feet to ground I tried this:
2 rays - middle of feet pointing down, middle of feet pointing up, max distance from ground = 1.15
4 rays - all rays from the lower corners of the bounding box pointing down, max distance from ground = 0.87
8 rays - 4 rays from lower corners pointing down, 4 rays pointing up, max distance from ground = 0.41

So it looks like I need 8 rays to get the most accurate reading. Now I can write code that says “if the avatars feet is more than 0.41 above the ground then she is actually flying, so play the flying animation”

1 Like

i think that possible with 3 raycast but need test

If there aren’t any bridges/caves/overhangs one can cast ray(s) from above the character, and skip any of the upwards rays. Then move the character to the pickedPosition + characterHeight, where characterHeight is however high they need to be to have their feet on the ground.

Good point! I just need to raise the origin of the ray a bit higher.

My solution is not perfect but I’m going to leave it for now. Someone walking up a car might start flying, but whatevs, its not the end of the world.

Ok, I’ve settled with this

When I walked off the car my algorithm determined that she was off the ground and automatically enabled flight mode (in reality one could easily step off the car, but I had to make some sacrifices). Then I manually flew (PG-UP and PG-DOWN keys) over the building and when I got close to the roof it automatically turned off flight mode, then when I walked off it turned on flight mode. That’s good enough for now.

I’m only use one raycast for this.

3 Likes

A technique often used in games is to create hidden planes, boxes and spheres that are only used for collision computations. They are actually a simplification of the complicated meshes in a scene and create artificial barriers/boundaries. E.g. for a tree you only create a collision box around the bark and not around the leaves.

See the red transparent planes in this article for an idea:

When you surround your car mesh with a few of these collision planes/boxes, you can reduce the computation complexity and lower the raycasts. And for example give the planes certain colors that trigger character movement options. E.g. a red plane = horizontal walk animation over it, a blue plane = vertical climb/descent animation, a green plane = don’t fly beyond this etc.

Just some thoughts…

Q

There is an ellipse (capsule collider) which detects collision and prevents a mesh from passing through another . The only problem is there is no “onCollision” event for this feature.

I wonder if some of us could work on a collision system (non-physics) that could cut up a massive scene, like a city, into small chunks and then do collisions with them. Really I wouldn’t go with the scene-centric angle, and instead would just make some sort of fancy data structure to which stuff is added in chucnks, but that may just be semantics. The octrees that are already available might work, I’m not sure. One issue though is that the meshes we put in these games aren’t really ready to be put into an octree in a meaningful way (or at least I don’t know how to do it). And by meaningful, I mean that the collision would have to be orders of magnitude faster. Just shoving a mesh of 3 story building into an octree doesn’t result in being able to walk on the floors or walk into walls without a ton of excess checks (it needs cut up first). Likeswise making a 3 story building out of 300 meshes will give us lots of little pieces to shove into a spatial structure that could do collisions efficiently (maybe), but is going to blow through the rendering budget.

I just made a multiplayer first person shooter and I’m pretty new to 3d, so I made a voxel system b/c i don’t know enough math to do anything else. I had a pre-existing networking engine that could do high player counts, and really I just wanted something to show off in 3D. The chunked voxel allowed the map to be really big (practically infinite), and there could be 50 players and hundreds of items falling on the ground without getting beyond 2% cpu worth of collisions. The voxel collisions are really cheap, b/c one can just divide the position of any object by the size of the voxels and we know what voxel it is in. No actual triangle-intersects-triangle type of math needed. The visible world is just a few meshes (1-9, depending on my world size). So this covered the two major performance problems that were in the way (fast collisions, small number of rendered meshes). But hey it’s voxels…

What I’d really want is similar performance on a world made out of arbitrary imported or generated meshes like terrain and buildings. I have no idea if some sort of general purpose solution is possible that could be shared among babylon users, or if anything that achieves this level of performance is pretty much married to the game it was made for (like the voxel thing). But I do totally plan on taking a deep R&D dive into this before the next game (~3-6 mo). Maybe we could start a thread prototyping techniques…

1 Like

https://github.com/BabylonJS/Babylon.js/blob/master/src/Meshes/abstractMesh.ts#L225

Isn’t that a mesh.ellipsoid onCollide event? Not sure. Maybe.

1 Like