Unity3D - “父级有一种布局组”错误
Posted
技术标签:
【中文标题】Unity3D - “父级有一种布局组”错误【英文标题】:Unity3D - "Parent has a type of layout group" error 【发布时间】:2018-10-30 07:41:46 【问题描述】:我在 Canvas 中有这个简单的结构:
游戏对象(垂直布局组) UI 图像(垂直布局组) TMP UGUI 文本(水平布局组,内容大小调整器)现在,它工作得很好,当文本超出边界时,UI-Image 会展开。 但是由于我有一个布局组作为我的 TMP 文本的父级,所以我在文本内的内容大小调整器中收到一个错误,说“父级有一种布局组组件......”。 结果,当我更改文本时,图像高度有时不会更新(不会增长或缩小,只有在我刷新或保存项目后)。
我在这里做错了吗?
【问题讨论】:
正如警告所说,父游戏对象(image_container)有一个布局组组件。内容大小调整器应该在没有布局组的游戏对象下 @Tricko 我知道。但我没有其他方法可以实现基于文本的扩展,所以我的问题是有什么替代方法可以做到这一点? 【参考方案1】:我将把它转换为答案,因为我要附上图片。我为聊天功能做了类似的事情。
使父级的内容尺寸更合适,并将水平或垂直尺寸设置为首选尺寸。
让其直接子元素成为背景,并为其添加一个布局元素以控制其最小尺寸。还要向它添加一个布局组以控制您将作为子项放置的文本。
将文本添加为背景的子项
更改文本以检查背景。
[编辑]
1.我把Parent的布局组改成VerticalLayoutGroup
。
2. 我复制了游戏对象“背景”,但使用不同的文本,您可以看到ContentSizeFitter
和VerticalLayoutGroup
如何控制孩子的大小。
在上面的屏幕截图中,我从未对 rect 变换进行任何调整。我只是更改了文本,如您所见,每个文本/对话框/消息的背景也进行了调整。
【讨论】:
您好,效果很好,但是如果我在聊天层中有另一个“垂直布局”(如果我们查看您的架构)怎么办? 父级上的VerticalLayout
的目的是什么?如果您有多个消息,只需复制上面示例中的游戏对象“背景”。我将编辑屏幕截图,以便您还可以检查父级中的 ContentSizeFitter
的工作方式。
非常感谢您的帮助和详细的回答:)【参考方案2】:
我被这个问题困扰了一年多,终于以正确的方式解决了。
解决方法很简单:
-
在父对象的布局组组件上勾选“控制子大小宽度/高度”。
删除任何子对象的内容大小调整器。
【讨论】:
【参考方案3】:制作了一个从原始 contentSizeFitter 组件复制的自定义脚本,我在其中添加了一个名为 applyToParent 的布尔值,如果“true”并且父级具有 rectTransform 组件,则父级将沿当前对象缩放。您甚至可以添加一个 recttransforms 变量列表,您可以使它们也遵循相同的大小! screenshot
using UnityEngine;
using UnityEngine.EventSystems;
namespace UnityEngine.UI
[AddComponentMenu("Layout/Custom Content Size Fitter", 888)]
[ExecuteAlways]
[RequireComponent(typeof(RectTransform))]
/// <summary>
/// Resizes a RectTransform to fit the size of its content & the ability to modify the size of the parent as well
/// </summary>
/// <remarks>
/// The ContentSizeFitter can be used on GameObjects that have one or more ILayoutElement components, such as Text, Image, HorizontalLayoutGroup, VerticalLayoutGroup, and GridLayoutGroup.
/// </remarks>
public class CustomContentSizeFitter : UIBehaviour, ILayoutSelfController
/// <summary>
/// The size fit modes avaliable to use.
/// </summary>
public enum FitMode
/// <summary>
/// Don't perform any resizing.
/// </summary>
Unconstrained,
/// <summary>
/// Resize to the minimum size of the content.
/// </summary>
MinSize,
/// <summary>
/// Resize to the preferred size of the content.
/// </summary>
PreferredSize
[SerializeField] protected FitMode m_HorizontalFit = FitMode.Unconstrained;
/// <summary>
/// The fit mode to use to determine the width.
/// </summary>
public FitMode horizontalFit get return m_HorizontalFit; set if (SetPropertyUtility2.SetStruct(ref m_HorizontalFit, value)) SetDirty();
[SerializeField] protected FitMode m_VerticalFit = FitMode.Unconstrained;
/// <summary>
/// The fit mode to use to determine the height.
/// </summary>
public FitMode verticalFit get return m_VerticalFit; set if (SetPropertyUtility2.SetStruct(ref m_VerticalFit, value)) SetDirty();
private DrivenRectTransformTracker m_Tracker;
protected CustomContentSizeFitter()
protected override void OnEnable()
base.OnEnable();
SetDirty();
protected override void OnDisable()
m_Tracker.Clear();
LayoutRebuilder.MarkLayoutForRebuild(rectTransform);
base.OnDisable();
protected override void OnRectTransformDimensionsChange()
SetDirty();
public virtual void SetLayoutHorizontal()
m_Tracker.Clear();
HandleSelfFittingAlongAxis(0);
/// <summary>
/// Calculate and apply the vertical component of the size to the RectTransform
/// </summary>
public virtual void SetLayoutVertical()
HandleSelfFittingAlongAxis(1);
[System.NonSerialized] private RectTransform m_Rect;
[System.NonSerialized] private RectTransform m_parentRect;
private RectTransform rectTransform
get
if (m_Rect == null)
m_Rect = GetComponent<RectTransform>();
return m_Rect;
private RectTransform parentRectTransform
get
if (m_parentRect == null)
m_parentRect = rectTransform.parent.GetComponent<RectTransform>();
return m_parentRect;
private void HandleSelfFittingAlongAxis(int axis)
FitMode fitting = (axis == 0 ? horizontalFit : verticalFit);
if (fitting == FitMode.Unconstrained)
// Keep a reference to the tracked transform, but don't control its properties:
m_Tracker.Add(this, rectTransform, DrivenTransformProperties.None);
return;
m_Tracker.Add(this, rectTransform, (axis == 0 ? DrivenTransformProperties.SizeDeltaX : DrivenTransformProperties.SizeDeltaY));
// Set size to min or preferred size
if (fitting == FitMode.MinSize)
rectTransform.SetSizeWithCurrentAnchors((RectTransform.Axis)axis, LayoutUtility.GetMinSize(m_Rect, axis));
else
rectTransform.SetSizeWithCurrentAnchors((RectTransform.Axis)axis, LayoutUtility.GetPreferredSize(m_Rect, axis));
if(applyToParent && parentRectTransform != null )
if(fitting == FitMode.MinSize )
parentRectTransform.SetSizeWithCurrentAnchors((RectTransform.Axis)axis, LayoutUtility.GetMinSize(m_Rect, axis));
else
parentRectTransform.SetSizeWithCurrentAnchors((RectTransform.Axis)axis, LayoutUtility.GetPreferredSize(m_Rect, axis));
public bool applyToParent = true;
protected void SetDirty()
if (!IsActive())
return;
LayoutRebuilder.MarkLayoutForRebuild(rectTransform);
#if UNITY_EDITOR
protected override void OnValidate()
SetDirty();
#endif
public static class SetPropertyUtility2
public static bool SetColor(ref Color currentValue, Color newValue)
if (currentValue.r == newValue.r && currentValue.g == newValue.g && currentValue.b == newValue.b && currentValue.a == newValue.a)
return false;
currentValue = newValue;
return true;
public static bool SetStruct<T>(ref T currentValue, T newValue) where T: struct
if (currentValue.Equals(newValue))
return false;
currentValue = newValue;
return true;
public static bool SetClass<T>(ref T currentValue, T newValue) where T: class
if ((currentValue == null && newValue == null) || (currentValue != null && currentValue.Equals(newValue)))
return false;
currentValue = newValue;
return true;
【讨论】:
【参考方案4】:最简单的解决方案,如果突然有其他人相关。
创建一个标准的 ScrollView,从中删除“内容”并添加文本而不是内容(不要忘记将文本添加到 ScrollRect 中的内容字段)。接下来,在文本中添加 ContentSizeFittier。enter image description here
【讨论】:
以上是关于Unity3D - “父级有一种布局组”错误的主要内容,如果未能解决你的问题,请参考以下文章
Unity3d 2021版本播放视频组件VideoPlayer报错The type name ‘VideoPlayer‘ could not be found in the namespace...