c# - Unity WorldToViewPortPoint not giving correct y position
问题描述
I have a script that places an UI element on the place where a 3d object is in 3d space. I do this in the following way:
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;
}
}
But this does not place the UI Element on the desired position. See the following images for more explaination.
in this case i want the TOPLEFT corner of the UI element to be ontop of the pink dot at the TOPLEFT of the whitecube. But as you can see the Y-axis doesnt quite match..
Some extra information about the conditions like canvas used and the prefab settings. See images below:
these are the canvas settings.
this are the Main Camera settings.
and this are the UI prefab settings.
If you need any more information or something isnt clear let me know so i can clarify!
the code is really inefficient and ugly but it is only for testing purposes :)
解决方案
A minimal edit to your code that gets the desired effect:
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;
}
}
Your UI image's pivot and anchors must be set to Bottom Left for this to work:
I've added code that will ensure the pivot and anchors are set this way. You may remove it as long as you ensure the prefabs have the bottom left preset, but it's safer this way.
The reasoning for doing it this way is the following:
Viewport coordinates have the 0,0 origin point in the bottom left, so if you set the pivot and anchors there it all lines up and you don't need to do any translation of coordinates - it just saves a lot of headache. The only thing that's left is to subtract the height of the UI Image in order to get it to line up vertically with the 3D cube.
推荐阅读
- tensorflow - .h5 文件中的 Keras(张量流)模型
- python - 在 python 中求解一个欠定的非线性方程组
- javascript - 参数'__0'和'value'的类型不兼容 - Typescript
- oracle - 如何在 Oracle AWS RDS 中授予 SYS 对象权限?
- amazon-cloudwatch - 具有特殊字符的 Cloudwatch JSON 过滤器模式
- angular - 使用 jest 和 angular 来测试翻译键 Lokalise 中占位符的内部 html 文本
- sql - 从表中查询在 PostgreSQL 的其中一列中包含某个键/值的记录
- javascript - Object.hasOwn() 与 Object.prototype.hasOwnProperty()
- ios - WCF 客户端为 iOS Unity 构建抛出空引用异常
- css - React-Bootstrap TypeScript - 如何创建 ImageButton