I want my world space document to face the camera.
But I have to say I got some problem obtaining center position of my document that is needed for this calculations.
But it is not enough because sometimes I need this pivot to be somewhere else.
I also would like to use this boundary information of UIDocument for other purposes, like aligning UIDocuments to some edges or to each-other. But right now proper facing the camera is a priority for me.
I’m still not able to resolve it, any news ?
I went to the source and there are some information needed for this calculations.
But damn, everything is internal.
I don’t think you need any internal API for this. This seems to work:
var doc = GetComponent<UIDocument>();
var root = doc.rootVisualElement;
var documentCenter = transform.TransformPoint(root.worldBound.center);
var lookVector = documentCenter - cam.transform.position;
transform.rotation = Quaternion.LookRotation(lookVector, cam.transform.up);
Then it’s up to you to adjust the arguments of Quaternion.LookRotation depending if you want it to face the camera or the camera plane, and how you want it to act vertically.
I start to understand what is going on, basically system is starting to return proper value at some point. This is why it works for you in Update method.
Take a look at this script, it will log the position of the UIDocument center and direction from center of the document to point (0,0,0).
public class UIDocumentTestComponent : MonoBehaviour
{
[SerializeField] private UIDocument document;
private void Awake()
{
LogPositionAndDirection(nameof(Awake));
document.rootVisualElement.RegisterCallback<GeometryChangedEvent>(OnGeometryChanged);
}
private void OnEnable()
{
LogPositionAndDirection(nameof(OnEnable));
}
private void Update()
{
LogPositionAndDirection(nameof(Update));
}
private void OnGeometryChanged(GeometryChangedEvent evt)
{
LogPositionAndDirection(nameof(OnGeometryChanged));
}
private void LogPositionAndDirection(string label)
{
var point = Vector3.zero;
var documentCenter = transform.TransformPoint(document.rootVisualElement.worldBound.center);
var direction = (point - documentCenter).normalized;
Debug.Log($"{label}: {documentCenter} : {direction}");
}
}
As we can see Awake and OnEnable returns NaN, but also first Update returns NaN.
After this we got OnGeometryChanged that returns something that is not right.
And finally we got stream of Update that started to return proper values.
I seriously don’t want to use Update method for this.
Best would be OnGemoetryChanged, but the one that is actually returning proper values.
Or something that lets me force building uidocument so I can obtain proper values immediately in Awake.
I can always hack it like this, but I see it problematic that we do not have a proper way to know when document is finally ready. Now when using LateUpdate or Update I will have to play with enable of my component during runtime so it is not called each frame. And I’m not even going deeper into situations when there are multiple documents whose positions/ dimensions depends on each-other.
And results returned by OnGeometryChanged - looks like a bug to me.