Prevent Teleport past walls/objects


I’m new to threejs in general but I’m using react-three-fiber. I’m following the Teleport example as my starting point and I’m using the same code they have written in Teleport.jsx.
This example sets up a square plane and the teleporting logic prevents the user from clicking outside the plane using <planeGeometry args={[19.4, 19.4]} /> which is slightly less than the actual dimensions 20x20. If I change the arguments passed to planeGeometry like <planeGeometry args={[29.4, 29.4]} /> I can teleport outside of the plane so nothing else is preventing that.

I want to expand on this example and I want to setup a plane that is not a square, let’s say an L-shaped plane like this

How can I restrict teleportation to the plane only ? I can setup a wall like this

but I can still teleport to the other side of the wall into the void like this

I’ve been looking at Raycasting and detecting if there is a wall in the way then I can prevent it that way but I’m wondering if there are better/easier techniques to accomplish this. Eventually I want a home floor plan with walls around it and I want to be able to walk around the home naturally without being able to go through walls.

Thank you !

Check out mesh-bvh and its character controls demo!

1 Like

where did this course come from suddenly? the code for this teleport demo is so small, i can’t believe it does what it does with so little.

as for your issue, you could wrap the camera inside the teleport component into a rt/rapier <RigidBody> with a <CapsuleCollider> inside, as well as the whole outward scene into a <RigidBody type="fixed">, and now instead of using to push it you would apply impulses. this is how the ecctl character controller works, it wraps the player/camera into a pill shape. the level is just wrapped into another rigidbody and that’s it.

i will ask erdong, the author of that controller library to look at your sandbox, it would be amazing if ecctrl could do that out of the box - so useful for virtual showcases and things like that.


ps, another idea to fix it quick would be to give the wall a onPointerDown (or onClick, it depends) and call e => e.stopPropagation(), the wall will now intercept the pointer. if the player can look over the wall though they could still click the ground behind so it would be limited.

1 Like

Thank you both, I’m looking into your suggestions. I did start working on implementing three-mesh-bvh. I have a boundingTree for both the circle pointer and the wall, just trying to figure out how to detect the right interception, I’ll need this for later so that the player doesn’t go through objects so this is helpful.
I will also look into Ecctrl

Thanks again !

1 Like

Hey guys, I’m back !

I’ve been exploring all options, creating a character control similar to what’s in three-mesh-bvh examples might be the way forward but I’m also using what I’m doing as a learning exercise so I hope you can help me answer this weird behavior.
I ended up using react-three/drei with the component wrapped around my components then I use raycaster.intersectObjects([state.wall1Ref.current], true) to detect the intersection on mouse click.

The problem I have currently is that the raycaster thinks that the wall starts from (0,0) which is the center of my room, so if I click anywhere on the plane highlighted in red, I get an intersection

However the wall is actually on position={[20.25, 0, 0.25]}, here is another screenshot
The red lines are the normals, and the faint green line is the BVH.

I updated my onPointerUp function with the following

        onPointerUp={(e) => {
          mouse.x = (e.clientX / window.innerWidth) * 2 - 1;
          mouse.y = -(e.clientY / window.innerHeight) * 2 + 1;
          raycaster.setFromCamera(mouse, camera);
          console.log(raycaster.intersectObjects([state.wall1Ref.current], true))

However this still didn’t fix the issue with the raycaster thinking that the mesh is in a different location.

Any idea why this is happening and how to correct it ?

Thank you !

Instead of having one large plane as the teleport listener, you could have different shapes, such as a path between walls.


Only the path is listening for the pointer events.
It is invisible, and the path edges don’t align with the wall edges. This is so you don’t teleport exactly to the wall edge.
Press the tick box top right to see the teleport listener boundary.

And, to stop a particular pointer event from going through a wall and being processed by something behind it, use stopPropagation()

  onPointerUp={(e) => {
  // ... a geometry resembling a wall

Thanks for the suggestion @seanwasere
This is a good solution !

Erdong added it to ecctrl

1 Like