Stop moveWithCollisions

Hey guys.
This time I make it short:

How can I stop the moveWithCollisions() function, to stop a mesh, after it reached a certain point?
Or maybe what I need, is to stop the scene.registerBeforeRender() function in which I call moveWithCollisions().
I know I also could use a normal animation, but I want to keep the collisions of the unit.

Playground

https://playground.babylonjs.com/#G6F8P6#4
In line 136 is the move() function which I call in line 92.

Leftclick a small box and rightclick somewhere on the ground afterwards.
The unit will go to the direction and then stop (with alert).
You can rightclick the big box to create another unit and do the same.

Problem:
I managed to let the unit stop, at clicked point on the ground. But when try to move again, it goes in a slight different direction, because the first moveWithCollision() is still active and it will never reach the second clicked point.

Greetings and thanks :slight_smile:

1 Like

Hi Modos,

I think you might be looking to handle events with observables. Check out this Playground; is this along the lines of what you were going for?

https://playground.babylonjs.com/#G6F8P6#5

Basically all I did was unregister the handler when we want to stop moving. I also added that behavior for a re-click, so now you can redirect your movement before your prior move has finished and it won’t get confused. The lines I changed are all in the “function to move units” code block, 136 to 155.

2 Likes

Hey, thanks so far.

That’s exactly what I looked for.
The downside of this is, that now only one unit (or one group of units) can move at the same time.
Is there a way to apply this approach directly to a mesh?

Otherwise I can imagine to create a new observable for every clicked/moved unit, so every unit that shall move has its own observable. Do you think it is possible?
(I’m asking because today I have not the time to try that anymore).

Applying a related approach per entity is definitely possible. The most canonical way to do that might be to add a Behavior to the entity’s parent Node, though you could could also make it happen by continuing to add observables. Another possible approach would be to have a single “move all the things” function that iterates every frame through a list of entity-destination pairs; that way, you can make things move or stop just by adding/removing them from that list. There are probably a bunch of other possible approaches, too; these were just the two that jumped to my mind. Which approach will work best for you depends on your overall design and what you’re planning to do in the bigger picture. :slight_smile:

Why didn’t I marked it as solved?
Because you did…
Probably because I wanted to try your mentioned possibilities to move all meshes at the same time.
For the time being I used the babylon navigation-mesh, but since they used animations for this I still want to try out your thoughts (didn’t do that yet…).

But I noticed a weakness of my old code:
When the meshes are pushed away because of collision, they just rushes past the goal and don’t stop.
I just saw the Vector3.Distance function and changed that now.

https://playground.babylonjs.com/#G6F8P6#15

Just in case somebody sees this thread and want to use this method.

1 Like

Short on time… didn’t read entire thread. I’ll get back with details.

a solution I use is to either avoid calling moveWithCollisions

OR

pass it 0 for x,y, or z…

I want to move them with collisions…except there is another way to move them with collisions.
Hopefully not some work around with iterating every frame over every mesh in the scene and registering intersect mesh.

Here is an update:
I tried an approach with @syntheticmagus suggestion.

move all the things” function that iterates every frame through a list of entity-destination pairs

https://playground.babylonjs.com/#G6F8P6#19
The result is indeed working, but the velocity of the meshes is increasing with every function call.
I guess it is, because the old movement is saved and just adds another, so the speed stacks.
Passing 0 to all directions is also not working. At least not, how I tried it.

So I need to use an observable for every mesh…or a combination of that and the move-all-things-function.

Hi Modos,

I think I failed to describe very clearly what I meant by a “move all the things” function. I tried out a slight modification of your move() function; is this somewhere along the lines of what you were going for?

https://playground.babylonjs.com/#G6F8P6#20

The modifications I made are marked with comments, lines 110 through 138. If that’s something like the behavior you were going for, I think there are only a few differences from what you already had:

  1. The “move all the things” function is always running, even when the list of things to move is empty. (It just doesn’t do anything in that case.) This makes the logic easy to keep track of and separates “picking a destination” and “moving” into two distinct operations.
  2. For each moving mesh on each frame, the logic calculates the next step it should take independent of what it did the frame before. This accounts for the fact that, because things are moving with collisions and “rubbing up against” other objects, the movement they make in a given frame is not always the movement they intended to make in that frame.
  3. When a new destination is picked, the move() function first removes all existing “move orders” from the moveList before adding the new one. Because of this, moveList always contains complete and exact information about who’s moving and where they’re going, every frame; everybody who’s in that list is moving, and everybody who’s not in that list isn’t. There are cleaner ways to do this with more sophisticated data structures (hash maps, etc.), but this was just to illustrate the behavior.

Again, don’t know if that’s exactly what you were going for, but hopefully this at least fleshes out my earlier, somewhat ambiguous recommendation to “move all the things.” :upside_down_face:

2 Likes

sm, AWESOME!!!

Indeed that is awesome! This is now the new solution to this topic.
Thank you very much. It is exactly what I imagined. Later I want to make something like a pathfinder (moving around meshes), but it is still to difficult and complicated for me.

The move function is not hard to understand, but let’s see about the moveObversable:

var moveVec = moveList[idx].target.subtract(moveList[idx].mesh.position);

moveVec is just goal.position - mesh.position.

if (moveVec.lengthSquared() > EPSILON * EPSILON) {
    var len = Math.min(MAX_MOVE_PER_FRAME, moveVec.length());
    moveVec.normalize().scaleInPlace(len);
    moveList[idx].mesh.moveWithCollisions(moveVec);
}

EPSILON seems to be the distance in which the mesh will stop in front of the picked point.
len is mostly MAX_MOVE_PER_FRAME, because the vector length is certainly always greater than 0.1.
moveVec will be scaled with MAX_MOVE_PER_FRAME (len), what does exactly the same as the name tells.

Is my understanding of the code correct? At least a bit? :smiley:

1 Like

Your understanding is pretty much perfect. :smile: The code will cause each entity to move as far as it can in a single frame unless that movement would take it past its destination (so, the last frame it moves), in which case it’ll try to move exactly onto its destination. Assuming that move was successful, moveVec.lengthSquared() should theoretically be zero the next frame; however, because it’s just best-practice to never directly compare floating point numbers for equality, I use EPSILON to check that the length is, if not zero, at most too small to care about.

2 Likes

Finally understanding Epsilon. Thanks for the confirmation. : )

1 Like