Reputation: 11
I'm pretty new when it comes to Unity and VR. I have to implement a teleport script and pretty much the only thing I know is that I can't move the camera itself because any changes to that are overwritten instantly. Instead, I use the XR Origin object as a locomotion platform and move that. The script is added as a component to the right hand and essentially just takes the XR Origin object and an XR Ray Interactor component from the hand and when I press the trigger it moves the XR Origin position to the position where the ray hits a teleportation area.
var hit = rayInteractor.TryGetHitInfo(out Vector3 position, out _, out _, out _);
if (hit && triggerPress.action.ReadValue<float>() == 1f)
{
player.transform.position = position;
}
However, the actual camera does not end up in the correct position as can be seen by debug output:
Camera: (0.84, 0.92, -0.94), XROrigin: (1.74, 0.00, -2.55), ray hit position: (1.74, 0.00, -2.55)
I do understand why that happens. The XR Origin object is a 1m² area and the camera can be at any point within that area so when I change the position of the XR Origin object the camera might simply not be in the middle of the object. I can fix that by setting the XR Origin scale to 0.1 for X and Z and that does result in pretty much perfect precision:
Camera: (4.02, 0.97, 0.14), XROrigin: (4.09, 0.00, 0.00), ray hit position: (4.09, 0.00, 0.00)
However, that also breaks the visuals. The hand is way too small and super far away from the camera:
in both screenshots the headset is at head height and the controller is lying on a table
How would I go about writing a teleport script that manages to teleport me to the exact location without breaking any visuals? Is there some trick I don't know about? Most tutorials are completely useless to me cause I need the teleportation to happen in VS and not just in Unity itself
Edit: here's a screenshot showing how extreme the differences are at times red circle marks where I actually ended up at
Edit 2: So two ideas how to fix it: 1) maybe the camera is set to a fixed position within the XR Origin object and I just need to adjust the starting positin of the camera and 2) I could just calculate the difference between camera and destination and add that to the XR Origin position. I can't test either until next week, though
Upvotes: 0
Views: 524
Reputation: 90813
I think if you only move the XROrigin
your camera still maintains the same offset relative to it as before.
What I mean by that is
XROrigin (0,0,0)
and Camera (1, 0, 0)
(because you already walked to the right)XROrigin (0, 0, 1)
I would expect your camera to actually end up at (1, 0, 1)
maintaining the offset.
I think what you should use instead is XROrigin.MoveCameraToWorldLocation(Vector3)
This function moves the camera to the world location provided by
desiredWorldLocation
. It does this by moving theXR Origin
object so that the camera's world location matches thedesiredWorldLocation
var hit = rayInteractor.TryGetHitInfo(out Vector3 position, out _, out _, out _);
if (hit && triggerPress.action.ReadValue<float>() == 1f)
{
player.GetComponent<XROrigin>().MoveCameraToWorldLocation(position);
}
might want to maintain current camera height though
var hit = rayInteractor.TryGetHitInfo(out Vector3 position, out _, out _, out _);
if (hit && triggerPress.action.ReadValue<float>() == 1f)
{
var xrOrigin = player.GetComponent<XROrigin>();
position.y = xrOrigin.Camera.transform.position.y;
xrOrigin.MoveCameraToWorldLocation(position);
}
NOTE: Regarding triggerPress.action.ReadValue<float>() == 1f
this might fail due to floating point precision. You should rather configure your action accordingly to only be triggered at a certain threshold in the first place and then rather use triggerPress.action.trigerred
Upvotes: 0