Unity WorldToViewPortPoint没有给出正确的y位置

时间:2018-08-29 22:10:56

标签: c# user-interface unity3d canvas mapping

我有一个脚本,用于将UI元素放置在3d空间中3d对象的位置。我通过以下方式执行此操作:

public class test : MonoBehaviour {

public Camera MainC;
public GameObject testc;

// Use this for initialization
void Start () {
    var ui = Object.Instantiate((GameObject)Resources.Load("uit"), Vector2.zero, Quaternion.identity);
    ui.transform.SetParent(GameObject.FindObjectOfType<Canvas>().gameObject.transform, false);

    var vertexs = testc.GetComponent<MeshFilter>().mesh.vertices;
    var trs = testc.GetComponent<Transform>();
    var cdc = new Vector2(GameObject.FindObjectOfType<Canvas>().GetComponent<RectTransform>().sizeDelta.x , GameObject.FindObjectOfType<Canvas>().GetComponent<RectTransform>().sizeDelta.y); 

    Object.Instantiate((GameObject)Resources.Load("pinksphere"), trs.transform.TransformPoint(vertexs[6]), Quaternion.identity); //bottomright
    Object.Instantiate((GameObject)Resources.Load("pinksphere"), trs.transform.TransformPoint(vertexs[5]), Quaternion.identity); //topleft

    var tl = MainC.WorldToViewportPoint(trs.transform.TransformPoint(vertexs[5]));

    var topleft = new Vector2(tl.x * cdc.x, tl.y * -(cdc.y) );
    ui.GetComponent<RectTransform>().anchoredPosition = topleft;
}

}

但这不会将UI元素放置在所需位置。有关更多说明,请参见以下图像。

enter image description here

在这种情况下,我希望UI元素的TOPLEFT角位于whitecube的TOPLEFT的粉红色点的顶部。但是如您所见,Y轴并不完全匹配。

有关条件的一些其他信息,例如使用的画布和预制设置。查看以下图片:

enter image description here 这些是画布设置。

enter image description here 这是主相机设置。

enter image description here 这是UI预制设置。

如果您需要更多信息或不清楚的地方,请告诉我,以便我进行澄清!
该代码确实效率低下且难看,但仅用于测试目的:)

1 个答案:

答案 0 :(得分:1)

对代码进行最少的编辑即可获得所需的效果:

public class Test : MonoBehaviour
{

    public Camera MainC;
    public GameObject testc;

    // Use this for initialization
    void Start()
    {
        var ui = Object.Instantiate((GameObject)Resources.Load("uit"), Vector2.zero, Quaternion.identity);
        ui.transform.SetParent(GameObject.FindObjectOfType<Canvas>().gameObject.transform, false);
        var uiRT = ui.GetComponent<RectTransform>();
        // Ensure uiRT's pivot and anchors are set to the bottom left preset.
        uiRT.anchorMin = Vector2.zero;
        uiRT.anchorMax = Vector2.zero;
        uiRT.pivot = Vector2.zero;

        var vertexs = testc.GetComponent<MeshFilter>().mesh.vertices;
        var trs = testc.GetComponent<Transform>();
        var cdc = new Vector2(GameObject.FindObjectOfType<Canvas>().GetComponent<RectTransform>().sizeDelta.x, GameObject.FindObjectOfType<Canvas>().GetComponent<RectTransform>().sizeDelta.y);

        Object.Instantiate((GameObject)Resources.Load("pinksphere"), trs.transform.TransformPoint(vertexs[6]), Quaternion.identity); //bottomright
        Object.Instantiate((GameObject)Resources.Load("pinksphere"), trs.transform.TransformPoint(vertexs[5]), Quaternion.identity); //topleft

        var tl = MainC.WorldToViewportPoint(trs.transform.TransformPoint(vertexs[5]));

        var offset = new Vector2(0, uiRT.sizeDelta.y);
        var topleft = tl * cdc - offset;
        uiRT.anchoredPosition = topleft;
    }
}

您的UI图像的轴和锚点必须设置为“左下角”才能起作用:

UI Image pivot and anchors set to bottom left

我添加了代码,以确保以这种方式设置枢轴和锚点。只要确保预制件具有左下预设,就可以将其删除,但是这样更安全。

这样做的原因如下:

视口坐标的左下角有0,0原点,因此,如果您在其中设置了轴并对其进行了锚定,则所有线都将对齐,并且您无需进行任何坐标转换-这省去了很多麻烦。剩下的唯一事情就是减去UI图像的高度,以使其与3D立方体垂直对齐。