【问题标题】:How to convert new Canvas ui image position to linerenderer position?如何将新的 Canvas ui 图像位置转换为 linerenderer 位置?
【发布时间】:2018-06-29 11:26:51
【问题描述】:

我在画布中有一个带有屏幕空间 - 相机渲染模式的图像 UI。我喜欢做的是通过循环遍历所有LineRenderer 位置并更改其y 轴,将我的LineRenderer 移动到图像垂直位置。我的问题是我无法获得LineRenderer 可以理解的图像的正确位置。我试过使用ViewportToWorldPointScreenToWorldPoint,但位置不同。

    Vector3 val = Camera.main.ViewportToWorldPoint(new Vector3(image.transform.position.x, image.transform.position.y, Camera.main.nearClipPlane));

    for (int i = 0; i < newListOfPoints.Count; i++)
    {
        line.SetPosition(i, new Vector3(newListOfPoints[i].x, val.y, newListOfPoints[i].z));
    }

使用Vector3 val = Camera.main.ScreenToWorldPoint(new Vector3(image.transform.localPosition.x, image.transform.localPosition.y, -10));的截图结果

绿色的LineRenderer 是改变y 位置的结果。它应该在方形图像的底部。

【问题讨论】:

  • 您能添加一张您当前代码呈现方式的屏幕截图吗?在屏幕空间和世界空间之间进行匹配是一件棘手的事情,它有助于了解发生了什么。
  • 打印出图像的屏幕空间位置如何?也许它不在你认为应该的位置。要尝试的另一件事是查看 (0, 0) 或 (100, 100) 转换为什么。
  • @YAC 真正的问题是覆盖画布对象使用与世界空间完全不同的坐标系......和视口空间。
  • @unice,如果您的问题解决了,请采纳答案,以便对其他人有用。
  • @Programmer,抱歉回复晚了。一直在测试脚本,它在 Canvas 中与渲染模式 Screen Space - Overlay 完美配合。但是当我使用 Screen Space - Camera 并将我的主相机拖到渲染相机时,linerenderer 的位置是不同的。但这足以回答我的问题,我现在将坚持覆盖。感谢 Draco18s 花费时间和精力回答我的问题 :)

标签: c# unity3d


【解决方案1】:

哇,这既烦人又复杂。

这是我最终得到的代码。您问题中的代码是Update() 函数的下半部分。我唯一改变的是传递给ScreenToWorldPoint() 方法的内容。该值在Update() 函数的上半部分计算。

RectTransformToScreenSpace() 函数改编自 this Unity Answer 帖子1 关于获取 RectTransform 的屏幕空间坐标(这正是我们想要从屏幕空间坐标转换回来进入世界空间!)唯一的区别是我得到了反向 Y 值,所以我从 Screen.height - transform.position.y 更改为 transform.position.y,这完美地完成了这个技巧。

之后,只需抓住该矩形的左下角,将其设为 Vector3 而不是 Vector2,然后将其传递回ScreenToWorldPoint()。唯一的技巧那里是因为透视相机,我需要知道线与相机最初的距离以保持相同的距离(否则线比图像更快地在屏幕上上下移动)。对于正交相机,此值可以是任何值。

void Update () {
    //the new bits:
    float dist = (Camera.main.transform.position - newListOfPoints[0]).magnitude;
    Rect r = RectTransformToScreenSpace((RectTransform)image.transform);
    Vector3 v3 = new Vector3(r.xMin, r.yMin, dist);

    //more or less original code:
    Vector3 val = Camera.main.ScreenToWorldPoint(v3);
    for(int i = 0; i < newListOfPoints.Count; i++) {
        line.SetPosition(i, new Vector3(newListOfPoints[i].x, val.y, newListOfPoints[i].z));
    }
}

//helper function:
public static Rect RectTransformToScreenSpace(RectTransform transform) {
    Vector2 size = Vector2.Scale(transform.rect.size, transform.lossyScale);
    Rect rect = new Rect(transform.position.x, transform.position.y, size.x, size.y);
    rect.x -= (transform.pivot.x * size.x);
    rect.y -= ((1.0f - transform.pivot.y) * size.y);
    return rect;
}

1从“如何获取 UI 对象的屏幕坐标”的广义搜索中找到 帖子并不容易。出现了一堆其他帖子并有一些代码,但没有一个能达到我想要的效果(包括将屏幕空间坐标转换回 UI 对象的世界空间坐标,这很简单而且不可逆,谢谢RectTransformUtility!)

【讨论】:

  • 我一直在寻找一种将 UI 转换为世界空间的方法,但没有时间设置场景来测试它。这真的有用吗?
  • @Programmer 在给出答案之前,我在 Unity 中测试了所有这些代码。有用。 :) 不过,我还没有准备好录制任何视频。 The whole class I usedimg 1 & img 2(我没有费心正确设置线渲染器)。左边缘与图像居中对齐,只是因为线渲染器上的第一个点位于 X=0(相机以 X 轴为中心)并且图像也以屏幕为中心。 Asker 的代码只关心 Y 位置。
  • 好吧好吧。稍后我将使用传出相机和画布模式设置对其进行测试。我认为您还应该将其设为 Vector3 函数,将 UI 空间转换为世界空间。我已经看到很多关于这个主题的被忽略的问题,这些问题需要将 UI 转换为世界位置。我想用这个重复的答案来结束其他旧的和未来的问题。
  • @Programmer 它只是从这个函数返回rect.center
猜你喜欢
  • 1970-01-01
  • 2015-03-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-06-13
  • 2012-03-11
  • 1970-01-01
相关资源
最近更新 更多