如何让孩子在Unity的GridLayoutGroup中占据世界地位?

时间:2017-11-30 10:34:24

标签: c# unity3d unity5

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

然而,我尝试了以下所有方法,最终都在屏幕上显示错误的位置(图像有时甚至移出屏幕)。

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

imageObject.transform.SetParent(otherObj, True);

2在第一种方式中使用SetParent方法,然后手动给图像一个位置,但id不会出现在鼠标位置(此代码适用于不在布局组中的其他对象):

imageObject.transform.SetParent(otherObj, True);
var p = Camera.main.ScreenToWorldPoint(Input.mousePosition);
imageObject.transform.position = new Vector3(p.x, p.y, 0);

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,因此不使用该值,因此值不是位置在屏幕上的位置,或者在帧的末尾发生了某些事情,所以我重置位置是没用的。

更多信息:我的画布渲染模式设置为"屏幕空间 - 摄像机"。但即使把它改成叠加,它仍然是相同的结果。 Canvas缩放器模式是"缩放屏幕尺寸",屏幕匹配模式是"展开"。

那么我该如何从GridLayoutGroup中取出图像,让它保持在屏幕上的位置?谢谢!

3 个答案:

答案 0 :(得分:1)

经过多次测试,我发现你拨打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);
 }

答案 1 :(得分:0)

好的,我已经做了测试项目。没有完全解决你的问题,但我让父母改变为位于0,0,0的GridLayoutGroup工作:

  1. 使用RectTransform.anchoredPosition获取相对位置 GridLayoutGroup
  2. 更改父级
  3. 确保图像的锚点保持不变(网格布局可以更改图像的锚点)。
  4. 更改父级以设置新锚点后等待帧结束。
  5. 为您的anchoredPosition设置新的RectTransform
  6. 如果你说你的GridLayoutGroup的规模与1,1,1不同 然后相应地划分/乘以坐标(0.5, 0.5, 0.5除以2)
  7. (如果您的网格不在(0,0,0)中,您可能还需要制作 一些路线)

答案 2 :(得分:0)

我使用此功能:

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();
}