I’m creating an AR sport in the place I want to virtualize an 8-ball pool desk. Since semantic labeling is virtually ineffective, I want to have some guide placement of objects and a few automatization. Nonetheless I can not seem to repair the location of the digital pockets for my desk. I’m inserting 3 pockets manually (from my preliminary perspective these are going to be backside left, left center and backside – the order may be argued, however it will be a hard and fast one), the opposite 3 pockets are going to be mechanically generated. Hovewer more often than not they’re weirdly rotated (as group round a pivot) as they’re all parented to a guardian sport object whose guardian is the script I’m utilizing to position the pockets and autogenerate the lacking ones.
The primary picture exhibits how my ther markers are positioned (aligning them goes to be one other challenge), the second how I think about it’s right and third one how more often than not the code flips it incorrectly to the appropriate.
The present code that handles the logic is the next:
utilizing Oculus.Interplay;
utilizing System.Collections.Generic;
utilizing TMPro;
utilizing UnityEngine;
public class PocketSetupManager : MonoBehaviour
{
[Header("Marker Placement Settings")]
[Tooltip("Prefab for the pocket marker (must have collider, rigidbody, Grabbable, HandGrabInteractable, etc.).")]
public GameObject markerPrefab;
public GameObject pocketMarkerRoot;
//OVR Controls
[Tooltip("Reference to left hand OVRHand component (for gesture detection).")]
public OVRHand leftHand;
[Tooltip("Reference to right hand OVRHand component (for gesture detection).")]
public OVRHand rightHand;
[Tooltip("Event sources for left and right source.")]
public OVRMicrogestureEventSource LeftHandEventSource;
public OVRMicrogestureEventSource RightHandEventSource;
[Tooltip("Reference to the hand visual components.")]
public HandVisual leftHandVisual;
public HandVisual rightHandVisual;
[Tooltip("Controller button to place a marker (fallback). e.g., Button.One = A (Right) or X (Left).")]
public OVRInput.Button placeMarkerButton = OVRInput.Button.One;
[Tooltip("Controller button to undo last marker (fallback). e.g., Button.Two = B (Right) or Y (Left).")]
public OVRInput.Button undoMarkerButton = OVRInput.Button.Two;
[Header("UI")]
[Tooltip("Floating instruction text displayed to the user")]
public TextMeshProUGUI instructionTextUI;
[Header("Privates")]
[Tooltip("Floating instruction text displayed to the user")]
[SerializeField]
personal string _instructionText = string.Empty;
[SerializeField]
personal sbyte _totalPockedNeeded = 3;
personal float _yCoordinateValueForMarkers = 0;
personal readonly string[] _pocketNames =
if (!_isInitialized ;
personal Listing<GameObject> _placedMarkers = new(6);
personal sbyte _markersPlacedCount = 0;
personal bool _groupModeActivate = false;
personal bool _allPocketsCalculated = false;
// Begin known as as soon as earlier than the primary execution of Replace after the MonoBehaviour is created
personal void Awake()
if (!_isInitialized
void Begin()
{
if (LeftHandEventSource == null || RightHandEventSource == null)
{
Debug.LogError($"No {nameof(OVRMicrogestureEventSource)} element hooked up to this gameobject.");
}
else
{
LeftHandEventSource.GestureRecognizedEvent.AddListener(gesture => OnMicrogestureRecognized(leftHand, gesture));
RightHandEventSource.GestureRecognizedEvent.AddListener(gesture => OnMicrogestureRecognized(rightHand, gesture));
}
}
// Replace known as as soon as per body
void Replace()
{
if (_groupModeActivate) return;
}
void OnApplicationQuit()
{
LeftHandEventSource.GestureRecognizedEvent.RemoveAllListeners();
RightHandEventSource.GestureRecognizedEvent.RemoveAllListeners();
}
personal void OnDestroy()
{
LeftHandEventSource.GestureRecognizedEvent.RemoveAllListeners();
RightHandEventSource.GestureRecognizedEvent.RemoveAllListeners();
}
public void OnMicrogestureRecognized(OVRHand hand, OVRHand.MicrogestureType gestureType)
{
Debug.Log($"Microgesture occasion: {gestureType} from hand {hand.title}.");
//Proper hand -> HandType is marked as inside.
var isRightHand = hand.title.ToLower().Accommodates("proper");
if (isRightHand)
{
swap (gestureType)
{
case OVRHand.MicrogestureType.ThumbTap:
PlacePocketMarker(hand);
break;
case OVRHand.MicrogestureType.SwipeRight:
FinalizePlacements();
break;
case OVRHand.MicrogestureType.SwipeLeft:
case OVRHand.MicrogestureType.SwipeForward:
case OVRHand.MicrogestureType.SwipeBackward:
default:
Debug.Log("Gesture presently not supported.");
break;
}
}
UpdateInstructionUI();
}
personal void FinalizePlacements()
{
if (_allPocketsCalculated)
{
_instructionText = "All pockets have been positioned at their revered positions. Nothing to do right here.";
Debug.Log(_instructionText);
UpdateInstructionUI();
return;
}
if (_markersPlacedCount < _totalPockedNeeded)
{
Debug.LogWarning("Can't finalize: not all required pocket markers are positioned but.");
return;
}
Vector3 bottomLeft = _placedMarkers[(byte)PocketName.BottomLeftCorner].rework.place;
Vector3 middleLeft = _placedMarkers[(byte)PocketName.MiddleLeftCorner].rework.place;
Vector3 bottomRight = _placedMarkers[(byte)PocketName.BottomRightCorner].rework.place;
//Prime left
Vector3 bottomLeftToLeftMiddle = middleLeft - bottomLeft;
Vector3 topLeft = bottomLeft + 2 * bottomLeftToLeftMiddle;
//Proper center
Vector3 bottomLeftToBottomRight = bottomRight - bottomLeft;
Vector3 middleRight = middleLeft + bottomLeftToBottomRight;
//Prime Proper
Vector3 topRight = topLeft + bottomLeftToBottomRight;
topLeft.y = _yCoordinateValueForMarkers;
middleRight.y = _yCoordinateValueForMarkers;
topRight.y = _yCoordinateValueForMarkers;
GameObject topLeftMarker = Instantiate(markerPrefab, topLeft, Quaternion.identification);
topLeftMarker.title = _pocketNames[(byte)PocketName.TopLeftCorner];
GameObject middleRightMarker = Instantiate(markerPrefab, middleRight, Quaternion.identification);
middleRightMarker.title = _pocketNames[(byte)PocketName.MiddleRightCorner];
GameObject topRightMarker = Instantiate(markerPrefab, topRight, Quaternion.identification);
topRightMarker.title = _pocketNames[(byte)PocketName.TopRightCorner];
if (pocketMarkerRoot != null)
{
topLeftMarker.rework.SetParent(pocketMarkerRoot.rework, true);
middleRightMarker.rework.SetParent(pocketMarkerRoot.rework, true);
topRightMarker.rework.SetParent(pocketMarkerRoot.rework, true);
}
_placedMarkers[(byte)PocketName.TopLeftCorner] = topLeftMarker;
_placedMarkers[(byte)PocketName.MiddleRightCorner] = middleRightMarker;
_placedMarkers[(byte)PocketName.TopRightCorner] = topRightMarker;
_markersPlacedCount = 6;
_instructionText = "All 6 pockets positioned!";
Debug.Log("All pockets positioned and finalized.");
_allPocketsCalculated = true;
UpdateInstructionUI();
}
personal void PlacePocketMarker(OVRHand hand)
{
if (_markersPlacedCount == _totalPockedNeeded)
{
_instructionText = "The entire required pockets have been instantiated. You may seize them and reposition them, earlier than swiping proper.";
UpdateInstructionUI();
return;
}
//if (_groupModeActivate) return;
if (pocketMarkerRoot == null)
{
Debug.LogError("No pocket marker root has been instantiated or has been deleted in runtime, so no (furher) pockets may be positioned.");
return;
}
var palmPosition = GetPalmWorldPosition(hand);
// For the primary pocket, retailer the Y-level
if (_markersPlacedCount == 0)
{
_yCoordinateValueForMarkers = palmPosition.y;
Debug.Log($"PalmPosition {palmPosition.y}");
Debug.DrawRay(palmPosition, Vector3.up * 0.1f, Shade.inexperienced, 2f);
}
// Override Y to all the time match the primary pocket’s Y
palmPosition.y = _yCoordinateValueForMarkers;
// Instantiate marker at (X,Z) of your hand + fastened Y
GameObject marker = Instantiate(markerPrefab, palmPosition, Quaternion.identification);
marker.title = _pocketNames[_markersPlacedCount];
marker.rework.SetParent(pocketMarkerRoot.rework, worldPositionStays: true);
_placedMarkers.Add(marker);
_markersPlacedCount++;
// Suggestions message
sbyte remaining = (sbyte)(_totalPockedNeeded - _markersPlacedCount);
_instructionText = remaining > 0
? $"<b>{marker.title}</b> positioned! {remaining} extra to go…"
: $"<b>{marker.title}</b> positioned! Swipe proper to substantiate.";
UpdateInstructionUI();
}
personal Vector3 GetPalmWorldPosition(OVRHand hand)
{
HandVisual handVisual = (hand == leftHand) ? leftHandVisual : rightHandVisual;
if (handVisual == null)
{
Debug.LogWarning("Hand visible element not assigned.");
return hand.rework.place;
}
return handVisual.GetTransformByHandJointId(Oculus.Interplay.Enter.HandJointId.HandPalm).place;
}
personal void UpdateInstructionUI()
{
if (instructionTextUI != null)
{
instructionTextUI.textual content = _instructionText;
_instructionText = string.Empty;
}
else
{
Debug.LogWarning("Instruction textual content UI not assigned.");
}
}
public void UndoLastMarker()
{
if (_markersPlacedCount == 0) return;
_markersPlacedCount--;
_markersPlacedCount = _markersPlacedCount < 0 ? (sbyte)0 : _markersPlacedCount;
}
}
The prefab of the pocket additionally comprises a scripts which limits the interplay to X and Z.
utilizing UnityEngine;
[RequireComponent(typeof(Transform))]
public class XZOnlyConstraint : MonoBehaviour
{
[Tooltip("Whether this marker can currently be grabbed by the user.")]
public bool GrabbableEnabled = true;
personal Vector3 _initialPosition;
personal Quaternion _initialRotation;
personal bool _isInitialized = false;
public void Initialize(Quaternion worldRotation)
{
_initialPosition = rework.place;
_initialRotation = worldRotation;
_isInitialized = true;
}
public void Initialize() => Initialize(rework.rotation);
personal void LateUpdate()
}
How one can aproach this challenge of inserting the pockets in order that I can sort out different elements of defining the play space and what I’m doing incorrect?
The important options of the pocket placement half are:
- Putting the pockets, having the manually positioned pockets aligned.
- Autogenerated the remaining pockets.
- Undoing some (or all) misplaced pockets.
- Confirming the location and maintain it someplace so somebody from the opposite Quest can acces it?