After Teleporting, pointer positions do not appear to update
SimonDarksideJ opened this issue · 11 comments
XRTK - Mixed Reality Toolkit Bug Report
Describe the bug
Hopefully, this is a simple knowledge issue, but I hit an issue regarding grabbing objects in a scene and placing it in the hand of the grabbed controller.
Whilst the user remains at 0 and walk around, there is no issue, grabbed objects are placed in the controller locations.
However, once a user has teleported, this ceases to work, even when parenting the grabbed object with the controller's parent. The transforms for each object are identical but their positions are not.
To Reproduce
-
Download sample project
GrabbingAndTeleporting.zip -
Check XR settings and run project
-
Grab each cube from current position - expected working ok
-
Teleport to a new position
-
Grab each cube again and notice they only move to the original, pre-teleport position.
Expected behavior
It should be possible to use the Events position to position object relative to the controller that initiated the event
Actual behavior
After teleporting, the new camera position is (under Playspace) is not taken into account, even if the object is parented to the playspace
Screenshots
TeleportationControllerPositionIssue.mp4
Additional Context
Here is the line where the grabbed object is parented to the controllers parent for reference:
transform.parent = eventData.InputSource.Pointers[0].Controller.Visualizer.GameObject.transform.parent;
Here is the full grab script that is used in the project for reference:
using UnityEngine;
using XRTK.Definitions.InputSystem;
using XRTK.Definitions.Utilities;
using XRTK.EventDatum.Input;
using XRTK.Interfaces.InputSystem.Handlers;
using XRTK.SDK.Input.Handlers;
using XRTK.Services;
/// <summary>
/// A simple grabbable interaciton handler component. This component was just
/// created for demo purposes and is not part of the XRTK SDK. Feel free to use it as a starting
/// point for your own component until XRTK has a proper component for it.
/// </summary>
/// <remarks>This component is not optimized for production use.</remarks>
public class GrabParentUpdate : BaseInputHandler, IMixedRealityInputHandler, IMixedRealityInputHandler<MixedRealityPose>
{
private bool isGripped;
private float lerpTime;
private Handedness gripHandedness;
private bool lerpBackToStart;
private Vector3 startPosition;
private Quaternion startRotation;
private Transform startParent;
[SerializeField]
private MixedRealityInputAction grabAction = MixedRealityInputAction.None;
[SerializeField]
private MixedRealityInputAction gripPoseAction = MixedRealityInputAction.None;
[SerializeField]
[Tooltip("If the distance to the grabbed object is above the threshold it will lerp towards the grab pose.")]
private float lerpDistanceThreshold = .05f;
[SerializeField]
[Tooltip("Grab pose lerp duration.")]
private float lerpDuration = 1f;
[SerializeField]
[Tooltip("Grip pose offset for the object.")]
private Vector3 gripPositionOffset = Vector3.zero;
private void Awake()
{
startPosition = transform.position;
startRotation = transform.rotation;
startParent = transform.parent;
}
private void Update()
{
if (lerpBackToStart)
{
var fraction = lerpTime / lerpDuration;
transform.position = Vector3.Slerp(transform.position, startPosition, fraction);
transform.rotation = Quaternion.Slerp(transform.rotation, startRotation, fraction);
lerpBackToStart = fraction < 1f;
lerpTime += Time.deltaTime;
}
}
public void OnInputChanged(InputEventData<MixedRealityPose> eventData)
{
if (eventData.used)
{
return;
}
if (eventData.Handedness == gripHandedness && eventData.MixedRealityInputAction == gripPoseAction && isGripped)
{
if (Vector3.Distance(transform.position, eventData.InputData.Position) <= lerpDistanceThreshold)
{
transform.position = eventData.InputData.Position + eventData.InputData.Rotation * gripPositionOffset;
transform.rotation = eventData.InputData.Rotation;
}
else
{
var fraction = lerpTime / lerpDuration;
transform.position = Vector3.Slerp(transform.position, eventData.InputData.Position + eventData.InputData.Rotation * gripPositionOffset, fraction);
transform.rotation = Quaternion.Slerp(transform.rotation, eventData.InputData.Rotation, fraction);
lerpTime += Time.deltaTime;
}
}
}
public void OnInputDown(InputEventData eventData)
{
if (eventData.used)
{
return;
}
if (!isGripped && eventData.MixedRealityInputAction == grabAction)
{
isGripped = true;
gripHandedness = eventData.Handedness;
transform.parent = eventData.InputSource.Pointers[0].Controller.Visualizer.GameObject.transform.parent;
if (MixedRealityToolkit.IsInitialized &&
MixedRealityToolkit.InputSystem != null)
{
MixedRealityToolkit.InputSystem.Register(gameObject);
}
lerpTime = 0f;
eventData.Use();
}
}
public void OnInputUp(InputEventData eventData)
{
if (eventData.used || eventData.Handedness != gripHandedness)
{
return;
}
if (eventData.MixedRealityInputAction == grabAction)
{
isGripped = false;
MixedRealityToolkit.InputSystem?.Unregister(gameObject);
eventData.Use();
lerpTime = 0f;
lerpBackToStart = true;
transform.parent = startParent;
}
}
}
Thanks for the detailed report.
@SimonDarksideJ this is the intended behavior.
The visualizers parent is the users local play space frame of reference (Scene/MixedRealityPlayspace
).
I suggest not even re-parenting the object, but instead using a solver or constraint to perform the desired action.
Could you better describe exactly what you're trying to accomplish here when you grab the cubes?
If you're just trying to synchronize the cube with your controller just use the eventData.InputSource.Pointers[0].Controller.Visualizer.GameObject.transform.position
(although you should really be using the IMixedRealityPointerHandler
if you're going to do anything with pointers).
If you're trying to synchronize the cube object with your local frame of reference you could set the position of the cube to the controller's transform position, then update the parent to the user's body Scene/MixedRealityPlayspace/PlayerBody
I think you missed the point @StephenHodgson
A simple fact is that the EVENTS the pointers emit expose the incorrect position after teleporting.
It works fine before teleporting but after teleporting the positions are wrong
I'll try writing a simple test script to demonstrate
@SimonDarksideJ specifically which property of the pointer is incorrect here?
Pointers don't emit any events afaik.
Pointers don't emit any events afaik.
They don't emit events correct, but the pointer data and its state is shared within an event.
You're not even using the pointer event data bc you haven't implemented the pointer handler in this class
The issue isn't the script, the script is just their to demonstrate the issue with the pointer event data location.
I see issues with the script. You're not even getting the pointer event data through the pointer handler.
You also still haven't answered my questions:
Could you better describe exactly what you're trying to accomplish here when you grab the cubes?
specifically which property of the pointer is incorrect here?
Let me get back to you on that one :D
Going to close this. Reopen when you're ready to update the information @SimonDarksideJ