C# 如何得到孩子';s在网格布局中的世界位置团结一致?

C# 如何得到孩子';s在网格布局中的世界位置团结一致?,c#,unity3d,unity5,C#,Unity3d,Unity5,我有一个滚动视图,在它的内容对象中有一个GridLayoutGroup组件(内容对象有自己的位置和比例,而不是(0,0,0)或(1,1,1)),它下面有几个图像。在运行期间,我希望取出一个图像并将其父对象设置为其他UI对象,但我希望图像保持其在屏幕上的位置 然而,我尝试了以下所有方法,结果都是屏幕上的位置错误(图像有时甚至在屏幕外移动) 1对图像对象使用SetParent方法(尝试将True或false作为第二个参数): 2以第1种方式使用SetParent方法,然后手动为图像指定位置,但id不

我有一个滚动视图,在它的内容对象中有一个GridLayoutGroup组件(内容对象有自己的位置和比例,而不是(0,0,0)或(1,1,1)),它下面有几个图像。在运行期间,我希望取出一个图像并将其父对象设置为其他UI对象,但我希望图像保持其在屏幕上的位置

然而,我尝试了以下所有方法,结果都是屏幕上的位置错误(图像有时甚至在屏幕外移动)

1对图像对象使用SetParent方法(尝试将True或false作为第二个参数):

2以第1种方式使用SetParent方法,然后手动为图像指定位置,但id不会出现在鼠标位置(此代码适用于不在layoutgroup中的其他对象):

3调用SetParent后,将位置设置为其原始值

var p = imageObject.transform.position;
imageObject.transform.SetParent(otherObj, True);
imageObject.transform.position = new Vector3(p.x, p.y, 0);
4不要使用任何代码,但在编辑器中运行时,手动将图像拖出到目标父对象。但它的立场还是改变了

5不要使用任何代码,但在编辑器中运行时,手动取消选中GridLayoutGroup以禁用它。图像位置仍然会改变

为什么第三条路不起作用?我想可能是图像对象的transform.position没有被使用,所以该值没有被使用,所以该值不在屏幕上的位置,或者在帧结束时发生了一些事情,所以我对该位置的重置是无用的

更多信息:我的画布渲染模式设置为“屏幕空间摄影机”。但即使将其更改为覆盖,结果仍然相同。画布缩放器模式为“随屏幕大小缩放”,屏幕匹配模式为“扩展”


那么,我应该怎么做才能将图像从GridLayoutGroup中取出,但让它保持在屏幕上的位置呢?谢谢

好的,我做了一个测试项目。没有完全解决您的问题,但我让位于
0,0,0
的GridLayoutGroup的家长更改工作:

  • 使用
    rectcransform.anchoredPosition
    获取中的相对位置
    GridLayoutGroup
  • 换父母
  • 确保图像的定位点保持不变(网格布局可以更改图像的定位点)
  • 在更改父对象后等待帧结束以设置新的锚定
  • 为您的
    RectTransform
    设置新的
    anchoredPosition
  • 如果正如您所说,您的GridLayoutGroup的比例不同于
    1,1,1
    然后相应地除以/乘以坐标(除以2表示
    0.5,
    0.5,0.5
  • (如果您的网格不在
    (0,0,0)
    中,您可能还需要 一些路线)

  • 经过几次测试,我发现调用
    SetParent(objParent,True)后的位置是正确的;但是由于与GridLayoutGroup相关的原因,在这之后和帧结束之前,位置会发生变化。所以,记录下这个位置,在其他帧中做你需要的任何事情

    例如:

    在主线程中:

     imageObject.transform.SetParent(otherObj, True);
     originalPosition = imageObject.transform.position;
     imageObject.SetObjectActive(false); // If not do this, the image might flicker at it's position before put it into the GridLayoutGroup. My guess is that it gets rendered before the AdjustTransInTheEndOfFrame method is executed.
     StartCoroutine(AdjustTransInTheEndOfFrame(imageObject));
    
     private IEnumerator AdjustTransInTheEndOfFrame(GameObject obj) 
     {
            yield return new WaitForEndOfFrame();
            obj.transform.position = originalPosition;
            obj.SetObjectActive(true);
     }
    
    我使用此功能:

    public Vector2 GetChildLocalPosition(RectTransform rectTransformGrid, RectTransform rectTransformChild)
    {
       var localPositionGrid = (Vector2)rectTransformGrid.localPosition;
       var sizeDeltaGrid = rectTransformGrid.sizeDelta;
       var deltaGridFromCenterToLeftTop = new Vector2(-0.5f * sizeDeltaGrid.x, 0.5f * sizeDeltaGrid.y);
    
       var anchoredPositionChild = rectTransformChild.anchoredPosition;
       var childPosition = localPositionGrid + anchoredPositionChild + deltaGridFromCenterToLeftTop;
       return childPosition;
    }
    
    
    如果需要,请更新GridLayoutGroup,如下所示:

    public void UpdateGrid(LayoutGroup gridLayoutGroup)
    {
       gridLayoutGroup.CalculateLayoutInputHorizontal();
       gridLayoutGroup.CalculateLayoutInputVertical();
       gridLayoutGroup.SetLayoutHorizontal();
       gridLayoutGroup.SetLayoutVertical();
    }
    

    我认为在例3中,您应该在设置父项之前存储位置。@obywan感谢您的回复。这是个错误,只是编辑了一下。我在代码中做得很好。谢谢,为什么要等到框架结束呢?我过去只使用示例中显示的简单方法,并使其工作,但我有一段时间没有进行测试,最近在我的项目中更改了太多代码和结构。现在我不能再像以前那样让它工作了:(关于WaitForEndOfFrame-如果你在更改父项后立即设置锚点,它将保持不变。不确定确切原因,可能是因为执行顺序。是的,WaitForEndOfFrame在打断我的头后为我做了这件事,解释了为什么我无法获得该职位。谢谢!!
    public Vector2 GetChildLocalPosition(RectTransform rectTransformGrid, RectTransform rectTransformChild)
    {
       var localPositionGrid = (Vector2)rectTransformGrid.localPosition;
       var sizeDeltaGrid = rectTransformGrid.sizeDelta;
       var deltaGridFromCenterToLeftTop = new Vector2(-0.5f * sizeDeltaGrid.x, 0.5f * sizeDeltaGrid.y);
    
       var anchoredPositionChild = rectTransformChild.anchoredPosition;
       var childPosition = localPositionGrid + anchoredPositionChild + deltaGridFromCenterToLeftTop;
       return childPosition;
    }
    
    
    public void UpdateGrid(LayoutGroup gridLayoutGroup)
    {
       gridLayoutGroup.CalculateLayoutInputHorizontal();
       gridLayoutGroup.CalculateLayoutInputVertical();
       gridLayoutGroup.SetLayoutHorizontal();
       gridLayoutGroup.SetLayoutVertical();
    }