Hello all,
Instead of using QR, we are planning to use 1 object to localize our XR app in iPhone. Since now I found this script and were trying to implement it but couldn’t succeed. PS. I am using ARKit and Unity 6.
Would be greatfull if you have any suggestions for resolve this : )
Thanks for your time.
using UnityEngine;
using UnityEngine.XR.ARFoundation;
using UnityEngine.XR.ARSubsystems;
using System.Collections.Generic;
public class ARWorldAlignmentHandler : MonoBehaviour
{
[SerializeField]
private ARTrackedObjectManager trackedObjectManager;
[SerializeField]
private GameObject xrOrigin; // Reference to XR Origin (AR Session Origin or XR Origin)
[SerializeField]
private Material trackedObjectMaterial; // Material to apply to tracked objects
private Dictionary<TrackableId, GameObject> trackedObjectInstances = new Dictionary<TrackableId, GameObject>();
private Dictionary<TrackableId, Pose> lastKnownTransforms = new Dictionary<TrackableId, Pose>();
private bool isWorldAligned = false;
void OnEnable()
{
if (trackedObjectManager != null)
{
trackedObjectManager.trackedObjectsChanged += OnTrackedObjectsChanged;
}
}
void OnDisable()
{
if (trackedObjectManager != null)
{
trackedObjectManager.trackedObjectsChanged -= OnTrackedObjectsChanged;
}
}
private void OnTrackedObjectsChanged(ARTrackedObjectsChangedEventArgs args)
{
// Handle added tracked objects
foreach (var trackedObject in args.added)
{
CreateOrUpdateTrackedObject(trackedObject);
AlignARWorldToTrackedObject(trackedObject);
}
// Handle updated tracked objects
foreach (var trackedObject in args.updated)
{
CreateOrUpdateTrackedObject(trackedObject);
// Uncomment the next line if you want continuous alignment when the tracked object updates
// AlignARWorldToTrackedObject(trackedObject);
}
// Handle removed tracked objects
foreach (var trackedObject in args.removed)
{
if (trackedObjectInstances.TryGetValue(trackedObject.trackableId, out GameObject instance))
{
lastKnownTransforms[trackedObject.trackableId] = new Pose(instance.transform.position, instance.transform.rotation);
Destroy(instance);
trackedObjectInstances.Remove(trackedObject.trackableId);
}
}
}
private void CreateOrUpdateTrackedObject(ARTrackedObject trackedObject)
{
if (trackedObjectInstances.TryGetValue(trackedObject.trackableId, out GameObject instance))
{
// Update existing tracked object instance position and rotation
instance.transform.position = trackedObject.transform.position;
instance.transform.rotation = trackedObject.transform.rotation;
lastKnownTransforms[trackedObject.trackableId] = new Pose(trackedObject.transform.position, trackedObject.transform.rotation);
}
else
{
// Create a new GameObject representing the tracked object
GameObject newObject = GameObject.CreatePrimitive(PrimitiveType.Cube);
newObject.transform.position = trackedObject.transform.position;
newObject.transform.rotation = trackedObject.transform.rotation;
// Assign the custom material to the new object if available
if (trackedObjectMaterial != null)
{
newObject.GetComponent<Renderer>().material = trackedObjectMaterial;
}
trackedObjectInstances[trackedObject.trackableId] = newObject;
lastKnownTransforms[trackedObject.trackableId] = new Pose(newObject.transform.position, newObject.transform.rotation);
}
}
private void AlignARWorldToTrackedObject(ARTrackedObject trackedObject)
{
if (!isWorldAligned)
{
// Desired position and rotation in Unity space (typically zero)
Vector3 desiredPosition = Vector3.zero;
Quaternion desiredRotation = Quaternion.identity;
// Calculate positional offset
Vector3 positionOffset = desiredPosition - trackedObject.transform.position;
// Calculate rotational offset
Quaternion rotationOffset = desiredRotation * Quaternion.Inverse(trackedObject.transform.rotation);
// Adjust xrOrigin's position and rotation
xrOrigin.transform.position += positionOffset;
xrOrigin.transform.rotation = rotationOffset * xrOrigin.transform.rotation;
isWorldAligned = true;
Debug.Log($"AR World aligned with tracked object. XR Origin position: {xrOrigin.transform.position}, rotation: {xrOrigin.transform.rotation}");
}
}
}