I have an iOS AR app that tracks multiple images and instantiates a prefab over each as a child. The prefabs include several AR components so the user can scale, rotate, and translate them. If I move the tracked image, the instantiated prefabs update their positions so that they remain over their parent images EXCEPT if the user has translated (dragged) the prefab. If they have, then the prefab does NOT change position and instead remains where it was in world space.
Does the AR Translatable component break this parenting?
How can I make sure that the prefabs properly update their positions?
Do I need to add code to the tracked images update event to specifically reset the prefabs position/parent?
More information.
After translating the spawned prefab, the corresponding AR Tracked Image appears to be destroyed!
// Event Handler
private void OnTrackedImagesChanged(ARTrackedImagesChangedEventArgs eventArgs)
{
foreach (var trackedImage in eventArgs.added)
{
//Debug.Log(trackedImage.referenceImage.name + " was added");
var imageName = trackedImage.referenceImage.name;
var imageTransform = trackedImage.transform;
InstantiateTrackedImagePrefab(imageName, imageTransform);
}
foreach (var trackedImage in eventArgs.updated)
{
Debug.Log(trackedImage.referenceImage.name + "was updated");
}
foreach (var trackedImage in eventArgs.removed)
{
// this doesnt actually work - the removed event never triggers
// Debug.Log(trackedImage.referenceImage.name + "was removed");
}
}
when eventArgs.updated is called any tracked Image that had a translated prefab returns the following error in XCode
NullReferenceException: Object reference not set to an instance of an object.
at UnityEngine.Component.get_transform () [0x00000] in <00000000000000000000000000000000>:0
at UnityEngine.XR.ARFoundation.ARTrackableManager`5[TSubsystem,TSubsystemDescriptor,TProvider,TSessionRelativeData,TTrackable].SetSessionRelativeData (TTrackable trackable, TSessionRelativeData data) [0x00000] in <00000000000000000000000000000000>:0
at UnityEngine.XR.ARFoundation.ARTrackableManager`5[TSubsystem,TSubsystemDescriptor,TProvider,TSessionRelativeData,TTrackable].CreateOrUpdateTrackable (TSessionRelativeData sessionRelativeData) [0x00000] in <00000000000000000000000000000000>:0
at UnityEngine.XR.ARFoundation.ARTrackableManager`5[TSubsystem,TSubsystemDescriptor,TProvider,TSessionRelativeData,TTrackable].Update () [0x00000] in <00000000000000000000000000000000>:0
I looked into the AR Translation component code and saw where it destroys the old Anchor (parent game object) when the drag is complete. Since I am attaching my prefabs directly to the tracked images, this is where my problem occurs.
I tried modifying my code to add in an empty GO “between” the tracked image’s transform (parent) and my instantiated prefab (child) but as soon as I end my drag action this “middle man” is destroyed and I end up with the same problem that had before where the tracked image and the new prefab are no longer related. So the updated tracked image event leaves the prefabs orphaned in world space. At least my tracked images aren’t being destroyed now
OK I think I have this fixed! I just needed to add in some code to the eventArgs.updated loop.
Basically I make sure that the prefab exists and if it does I manually reset it’s position and rotation and re establish the hierarchy.
Hey rsauchuck-gp, could you please share the code for how you did this? I’m having the same problem since I’m attaching some canvas stuff to the parent as well.
In my initial code, on line 9, I call the function that attaches the prefab directly to the image’s transform. This is why it breaks. Instead i need to add a “middleman” GO and instantiate the prefab on THAT instead
var anchor = new GameObject("PlacementAnchor").transform;
anchor.position = imageTransform.position;
anchor.rotation = imageTransform.rotation;
anchor.parent = imageTransform;
InstantiateTrackedImagePrefab(imageName, anchor);
THEN on line 14 in the .updated block I add in the following
var imageName = trackedImage.referenceImage.name;
Debug.Log(imageName + "was updated");
if (instantiatedPrefabs.ContainsKey(imageName))
{
instantiatedPrefabs[imageName].transform.parent.transform.position = trackedImage.transform.position;
instantiatedPrefabs[imageName].transform.parent.transform.rotation = trackedImage.transform.rotation;
instantiatedPrefabs[imageName].transform.parent.transform.parent = trackedImage.transform;
}