private void Update()
    {
        if (!SimpleWebXR.InSession)
        {
            return;
        }

        if (SimpleWebXR.LeftInput.AxesCount < 4 || SimpleWebXR.RightInput.AxesCount < 4)
        {
            return;
        }

        var axe2 = SimpleWebXR.LeftInput.Axes[2] + SimpleWebXR.RightInput.Axes[2];
        var axe3 = SimpleWebXR.LeftInput.Axes[3] + SimpleWebXR.RightInput.Axes[3];

        if (axe3 != 0)
        {
            MixedRealityPlayspace.Transform.Translate(-Vector3.forward * Time.deltaTime * NOMINAL_TRANSLATION_SPEED * axe3, Camera.main.transform);
        }

        if (axe2 != 0)
        {
            MixedRealityPlayspace.RotateAround(Camera.main.transform.position, Vector3.up, Time.deltaTime * NOMINAL_ROTATION_SPEED * axe2);
        }
    }
        private void ProcessTeleportationRequest(TeleportEventData eventData)
        {
            isProcessingTeleportRequest = true;

            targetRotation = Vector3.zero;
            var teleportPointer = eventData.Pointer as IMixedRealityTeleportPointer;

            if (teleportPointer != null)
            {
                targetRotation.y = teleportPointer.PointerOrientation;
            }
            targetPosition = eventData.Pointer.Result.Details.Point;

            if (eventData.HotSpot != null)
            {
                targetPosition = eventData.HotSpot.Position;

                if (eventData.HotSpot.OverrideTargetOrientation)
                {
                    targetRotation.y = eventData.HotSpot.TargetOrientation;
                }
            }

            float height = targetPosition.y;

            targetPosition  -= CameraCache.Main.transform.position - MixedRealityPlayspace.Position;
            targetPosition.y = height;

            MixedRealityPlayspace.Position = targetPosition;
            MixedRealityPlayspace.RotateAround(
                CameraCache.Main.transform.position,
                Vector3.up,
                targetRotation.y - CameraCache.Main.transform.eulerAngles.y);

            isProcessingTeleportRequest = false;

            // Raise complete event using the pointer and hot spot provided.
            RaiseTeleportComplete(eventData.Pointer, eventData.HotSpot);
        }
        /// <inheritdoc />
        public override void OnInputChanged(InputEventData <Vector2> eventData)
        {
            // Don't process input if we've got an active teleport request in progress.
            if (isTeleportRequestActive || CoreServices.TeleportSystem == null)
            {
                return;
            }

            if (eventData.SourceId == InputSourceParent.SourceId &&
                eventData.Handedness == Handedness &&
                eventData.MixedRealityInputAction == teleportAction)
            {
                currentInputPosition = eventData.InputData;
            }

            if (currentInputPosition.sqrMagnitude > InputThresholdSquared)
            {
                // Get the angle of the pointer input
                float angle = Mathf.Atan2(currentInputPosition.x, currentInputPosition.y) * Mathf.Rad2Deg;

                // Offset the angle so it's 'forward' facing
                angle += angleOffset;
                PointerOrientation = angle;

                if (!TeleportRequestRaised)
                {
                    float absoluteAngle = Mathf.Abs(angle);

                    if (absoluteAngle < teleportActivationAngle)
                    {
                        TeleportRequestRaised = true;

                        CoreServices.TeleportSystem?.RaiseTeleportRequest(this, TeleportHotSpot);
                    }
                    else if (canMove)
                    {
                        // wrap the angle value.
                        if (absoluteAngle > 180f)
                        {
                            absoluteAngle = Mathf.Abs(absoluteAngle - 360f);
                        }

                        // Calculate the offset rotation angle from the 90 degree mark.
                        // Half the rotation activation angle amount to make sure the activation angle stays centered at 90.
                        float offsetRotationAngle = 90f - rotateActivationAngle;

                        // subtract it from our current angle reading
                        offsetRotationAngle = absoluteAngle - offsetRotationAngle;

                        // if it's less than zero, then we don't have activation
                        if (offsetRotationAngle > 0)
                        {
                            // check to make sure we're still under our activation threshold.
                            if (offsetRotationAngle < 2 * rotateActivationAngle)
                            {
                                canMove = false;
                                // Rotate the camera by the rotation amount.  If our angle is positive then rotate in the positive direction, otherwise in the opposite direction.
                                MixedRealityPlayspace.RotateAround(CameraCache.Main.transform.position, Vector3.up, angle >= 0.0f ? rotationAmount : -rotationAmount);
                            }
                            else // We may be trying to strafe backwards.
                            {
                                // Calculate the offset rotation angle from the 180 degree mark.
                                // Half the strafe activation angle to make sure the activation angle stays centered at 180f
                                float offsetStrafeAngle = 180f - backStrafeActivationAngle;
                                // subtract it from our current angle reading
                                offsetStrafeAngle = absoluteAngle - offsetStrafeAngle;

                                // Check to make sure we're still under our activation threshold.
                                if (offsetStrafeAngle > 0 && offsetStrafeAngle <= backStrafeActivationAngle)
                                {
                                    canMove = false;
                                    var height      = MixedRealityPlayspace.Position.y;
                                    var newPosition = -CameraCache.Main.transform.forward * strafeAmount + MixedRealityPlayspace.Position;
                                    newPosition.y = height;
                                    MixedRealityPlayspace.Position = newPosition;
                                }
                            }
                        }
                    }
                }
            }
            else
            {
                if (!canTeleport && !TeleportRequestRaised)
                {
                    // Reset the move flag when the user stops moving the joystick
                    // but hasn't yet started teleport request.
                    canMove = true;
                }

                if (canTeleport)
                {
                    canTeleport           = false;
                    TeleportRequestRaised = false;

                    if (TeleportSurfaceResult == TeleportSurfaceResult.Valid ||
                        TeleportSurfaceResult == TeleportSurfaceResult.HotSpot)
                    {
                        CoreServices.TeleportSystem?.RaiseTeleportStarted(this, TeleportHotSpot);
                    }
                }

                if (TeleportRequestRaised)
                {
                    canTeleport           = false;
                    TeleportRequestRaised = false;
                    CoreServices.TeleportSystem?.RaiseTeleportCanceled(this, TeleportHotSpot);
                }
            }

            if (TeleportRequestRaised &&
                TeleportSurfaceResult == TeleportSurfaceResult.Valid ||
                TeleportSurfaceResult == TeleportSurfaceResult.HotSpot)
            {
                canTeleport = true;
            }
        }