Reputation: 13
I'm developing an AR app using Unity, Vuforia, and HoloLens. My goal is to create a sphere at a specific position relative to a Vuforia image target (e.g., (1, 2, 3) relative to the image target's origin).
What I've Tried:
Manually: I created a sphere at (1, 2, 3) in the Unity Inspector as a child of the Vuforia image target, and it appeared at the correct position. Via Script: However, when creating the sphere through a script, its position is not as expected.
Code: In my script, I attempt to position the sphere as follows:
sphere.transform.position = targetTransform.position + localPosition;
Here, targetTransform
is the Transform
of the ObserverBehaviour
(Vuforia's target). Despite this, the sphere appears in a different location compared to the manually placed sphere.
Full Script:
Here’s the relevant part of my code for creating and positioning the sphere:
public class SphereManager
{
private GameObject sphere;
private Vector3 localPosition;
public SphereManager(Vector3 position)
{
localPosition = position;
}
public void CreateSphere(Transform targetTransform)
{
if (sphere == null)
{
sphere = GameObject.CreatePrimitive(PrimitiveType.Sphere);
sphere.transform.SetParent(targetTransform, false);
sphere.transform.position = targetTransform.position + localPosition;
sphere.transform.localScale = new Vector3(0.5f, 0.5f, 0.5f);
}
}
public void DestroySphere()
{
if (sphere != null)
{
GameObject.Destroy(sphere);
sphere = null;
}
}
public bool IsSphereActive() => sphere != null;
}
And the script handling the Vuforia target detection:
public class SphereCreator : MonoBehaviour
{
public Vector3 pose = Vector3.zero;
private SphereManager sphereManager;
private ObserverBehaviour observerBehaviour;
void Start()
{
sphereManager = new SphereManager(pose);
observerBehaviour = GetComponent<ObserverBehaviour>() ?? GetComponentInChildren<ObserverBehaviour>() ?? GetComponentInParent<ObserverBehaviour>();
if (observerBehaviour)
{
observerBehaviour.OnTargetStatusChanged += OnTargetStatusChanged;
}
else
{
Debug.LogWarning("ObserverBehaviour component not found.");
}
}
private void OnTargetStatusChanged(ObserverBehaviour behaviour, TargetStatus targetStatus)
{
if (targetStatus.Status == Status.TRACKED || targetStatus.Status == Status.EXTENDED_TRACKED)
{
sphereManager.CreateSphere(behaviour.transform);
}
else
{
sphereManager.DestroySphere();
}
}
private void OnDestroy()
{
if (observerBehaviour != null)
{
observerBehaviour.OnTargetStatusChanged -= OnTargetStatusChanged;
}
}
}
Problem:
The sphere created via the script doesn't align with the one placed manually in the Inspector. How should I set the sphere's position in the script to ensure it matches the manually placed sphere?
Upvotes: 0
Views: 66
Reputation: 154
The following line changes the world coordinate of the sphere but not its local position relative to the Vuforia image target.
sphere.transform.Position = targetTransform.position + localPosition;
You can replace it with:
sphere.transform.localPosition = localPosition;
Upvotes: -1
Reputation: 90570
The position you see and configure in the Inspector is the Local Position relative to the parent!
So if you want to set the same via script and it is a child of the target all you need to do is
sphere.transform.localPosition = localPosition;
Assuming that localPosition
here matches your expected value of 1,2,3
The reason it doesn't match when using the global positioning
sphere.transform.position = targetTransform.position + localPosition;
Is that here you don't take into account any scaling or rotation of the parent object target
.
If you really wanted to do it in world space - for instance if you want to achieve the same but without making the sphere a child - you could achieve this going through TransformPosition
sphere.transform.position = targetTransform.TransformPoint(localPosition);
This converts the local position into world space taking into account any parent translation, rotation and scale.
Though as the sphere is a child of the parent anyway I would strongly prefer the above for simplicity ;)
Upvotes: 1