How do you update the WebXR camera if inside a moving elevator/space ship/car?

There are several scenarios where I would like to update a player’s position when they are in or on another mesh. For example a player steps onto an elevator platform, presses a button and then is lifted up with the platform. Or several players are on a ship and when the ship’s position is translated, all the riders move relative to the boat.

This resembles a classic parenting issue where the child is the webxr camera and the players can still teleport around on the ship but wherever the ship moves all the players are moved too. Maybe the child is not permanently parented, because I still want to allow the player to step off of the elevator and let the elevator go back down independently.

I tried to put together a parenting test in this playground but it doesn’t seem to work https://playground.babylonjs.com/#F41V6N#301

I parented the webxr camera to a sphere and then I lift the sphere, but the camera’s immersive POV doesn’t seem to move. I’m using the webxr emulator (haven’t tried this on the Quest yet)

Am I doing something wrong? Or maybe there is a better technique to do this?

1 Like

Parenting an XR camera will be very confusing for the user. The minute you add rotation to the equation the entire scene will look incorrect. It is not technically disabled, but the internal teleportation mechanism (which allows you to move in XR) only works in local coordinates, as they are expected to be global (read this sentence 3 times, made sure it makes sense :-))

If you want to move an xr camera up an elevator, change the camera’s position along with the elevator. Something like this:

try parent webxr camera to moving object | Babylon.js Playground (babylonjs.com)

Another way is more complex but will provide better results - create a child where the camera is expected to be and copy its absolute position on each frame. Something like this:

try parent webxr camera to moving object | Babylon.js Playground (babylonjs.com)

1 Like

Thanks! Will continuously copying the position information onto the xrcamera “fight” or override the device movement information? Wouldn’t it make it difficult to move freely (crouch down) while on a platform?

I checked with my quest before posting, this compensates the device’s real world position correctly.
What it does it practically a constant teleportation.

Kind of related. I do not need to do this soon, but want to have a toggle button named “Recliner Mode”, and another button “Adjust”.

While the user can move around the scene, they may just wish to recline back and watch the show, as if they were sitting upright. Is this sound possible? Would only want to adjustment the X Level when they toggle on or hit the “Adjust”, so minor changes would be reflected.

You should create a path and animate the camera accordingly. The relative position will be applied to it on each frame. The user will be able to move around in the real world, and it will reflect in the scene as well, but the relative point to the scene will change.

Ok, but just checking, the user will actually be in a chair reclined back. I just want them to not be looking at the ceiling. Is the animation, just a means to an end?

The user sitting in a chair looking at a certain point is your real world transformation. WebXR let’s you change the point relative to the scene in which the user is at. so changing the camera position 5 units forward will move them 5 units forward in the babylon scene plus it’s real world transformation. If you don’t want the user to look at the sky in the scene, you will need to rotate the camera correctly

Hi there.
I was following this thread today because I have the exact same problem.

I have a webxr camera that is constantly going in the z axis direction, no matter what is the rotation of my head. I want all rotation and head tracking preserved while constantly moving forward. Think about being in a train wagon, when I travel at the train speed, by I can stand or sit, or walking back and forth.

Actually changing only the z position of the camera during render is going to override any other position (e.g. the x, y positions are no more affected by head tracking, there’s is apparently no compensation at all).

In those playground examples I have the same problem, if you try to move the head left or right it won’t budge and you don’t see the object from different positions, the sphere is always at the center of the view. It’s like the entire positioning is messed up when the position is done both by headtracking and manual setting the variable.

Maybe it’s my chrome webxr simulator? I had the same problem with my game in quest 2 testing.

UPDATE: I think that this is the same requirement for games like Pistol Whip or similar. You have to dodge bullet and walls, but you always move forward at the same time. I know this can be done with an inverse approach where is the world that moves around you, but everything becomes a lot more complicated.

At its current state the WebXR camera cannot have a parent. This is mainly done so because we are taking the data coming straight from WebXR (position/rotation, view matrices etc’) and pass them directly to the WebXR camera. We can explore the possibility to add a parent to the camera, which will allow you to define the train wagon or the train itself as the parent of the camera. This way the camera itself stays in one position (and is updated by the device), but the train’s position that is constantly updated will change the user’s global position.

This issue was (supposed to be) fixed already, we will check that.

Hello. Any news?
I sorted out inverting the movements (centered camera against moving world), but if I’m to introduce physics, not sure what could happen!

Hi @Mizar01 ,

Moving the camera on each frame to emulate moving forward does work as expected. We are still working on allowing the XR camera to be parented to other components. I sadly can’t provide a timeline, but babylon 5.0 will have it for sure.

1 Like

Hi.
Thanks for the response, but as I see the examples you provided do not let the head move freely(you can move the head or walk but the camera always remains in the same world position, there’s no compensation), only rotation works.
As for now i’m not interested in parenting, as long as i can force basic position translation every frame on a specific axys.
Can you provide an example? Or maybe I can try to provide one counter example…

Hello, RaananW. I’m coming into this discussion very late, but I got excited about the results of experimenting with the “parenting webxr camera to moving object” code and thought I’d share what worked for me, and also find out from you if I’ve got the right idea. (I also have a question about opting out of this parented state and going back to teleportation on the floor level.):

I wanted to know how to control the childForCamera sphere that the camera is parented to and thought I could do it as if/else statements, treating the xr.baseExperience.sessionManager code like an OnEveryFrame trigger. I wasn’t sure it would work the same way, but I was shocked that it did! I used a sphere as a point-and-click trigger to set the const elevator to 1 in order to move the sphere (sphere4 in the code snippet below) along the x axis.

xr.baseExperience.sessionManager.onXRFrameObservable.add(()=>{
if(elevator == 0){
sphere4.position.y += 0.01;
}
else if(elevator == 1){
sphere4.position.x += 0.01;
}

Not only did that work, but it worked beautifully! I now see it as a possible way to create something similar to walking or gliding through an underground “city” I’m working on.

I haven’t experimented with “opting out” of the parented camera mode yet (and using teleportation instead), but I was wondering how it could be done. Could I use a similar if else statement to unparent the camera–by unparenting the childForCamera from the sphere?

Thanks a lot for the great codes and information! It started my day off on the right foot.

No, the unparenting didn’t work. I realize I have to study the whole camera-parenting script a little bit more, and probably do something like stop copying the absolute position of the child to each frame. Still, it’s working well to move my camera around in any direction the player chooses, and I’m starting to develop an idea for using this for smooth-walking or gliding around on the floor level of my “city” instead of teleporting.

@RaananW will be back soon to have a look :slight_smile:

First - I am so happy that you everything (mostly) worked as expected :slight_smile:

Would be great if you can share a reproduction of what’s not working, so we can work with the same codebase. Do you have a playground you can share?

1 Like

Sorry, I didn’t see your reply till now (working too many hours). I’m in the process of creating a Playground for the project right now, but I just started using Babylonjs for the first time in a year and a half and have to refresh my memory on how to use GitHub for setting up the repository and using it in the Playground, etc. I’m getting there, though!

I do have a web page for the project, which is very much under construction. It’s “built” on top of the Color Picker WebXR example code–my first attempt at WebXR, started about two or three weeks ago. I used your “elevator” code in combination with a mesh-picking code, movePOV, and a few other workarounds to “glide” the Player/camera (parented to a sphere) to two box objects that are set in the floor meshes by pointing and clicking the controller anywhere on the floors. When the sphere enters a small x and z position “area” surrounding the top box mesh, the movePOV is halted, and the boxes are moved far away, out of the scene, as a way to prevent the camera from jittering, which is a problem I had while testing. Both the “city/complex” floor and the long ramp floor leading to the tall, unfinished tower are clickable. When you click the ramp, the boxes appear there correctly, and the camera glides up to the top box object at a sloping angle. Eventually I will make the box meshes and the parent sphere invisible, and I’ll create separate floor meshes for each room and corridor that are enabled/disabled so that the player can’t walk through walls.
Here’s the web page (although I’m not sure if it’s okay for me to provide a link in this forum):
https://secrettreasurepath.com/Hidden/colorpickerxr2.html

As Mizar01 said, in this childForCamera mode, only rotation works, so the player can’t walk around in the room space. Because I spent all my time working on this gliding process, I didn’t attempt any more experimentation with leaving the childForCamera mode, although I did see that there’s an option for onInitialXRPoseSetObservable.remove instead of .add. I haven’t tested that yet. Hopefully tonight and tomorrow I’ll have all of my project files uploaded for the Playground. Sorry I didn’t have that already prepared!

Edit: I used this as Christmas greeting for my sister, which explains why the Christmas tree is standing in one of the rooms…

Edit: I changed to a different Playground version below, with comments. The main focus of my question about leaving the “childForCamera” or elevator mode is found at line 307 in the code. That’s also where I have the inactive childForCamera.setParent(null)

Here’s a Playground of just the childForCamera and pickedMesh movement. As I mentioned above in my last reply post, clicking the floor and the ramp leading away from the floor positions two elongated boxes in the floor mesh and sets the elevator variable to move sphere4/camera to the top elongated box using your childForCamera code::
https://playground.babylonjs.com/#FGI273#126

The point where sphere4/camera has reached the landing spot is where I wish to have the camera (player) leave the childForCamera state and be free to move around according to the player’s head and body movements (real-world movement), and also allow the player to teleport. As I mentioned in my previous post, I saw that there’s the possibility of using onInitialXRPoseSetObservable.remove, but I haven’t tested that yet. Because I don’t fully understand that part of the script, I’m not sure if “remove” would work to release the camera from the sphere4 and childForCamera position-matching. I’m on break at work now, so I’m away from my computer. Thanks a lot for considering this issue!