如何在Unity3D中移除按钮之间的间距?

3
我正在Unity中设计的游戏中以编程方式创建按钮。我实例化按钮预制件并将它们作为子对象放在画布上的面板对象中。我已经设置了该面板的水平布局组,并具有以下属性:

enter image description here

我已经将以下组件添加到按钮预制件中,以实现我需要的外观:

enter image description here

在完成所有这些步骤后,我得到了以下结果:

enter image description here

因此,我的问题是,我如何删除每个按钮之间的间距?按钮应该紧贴在一起(但不重叠),看起来像一个句子。我之所以有单独的按钮,是为了让用户在句子中点击正确的两个字母字符(在上面的示例中是字母ar)。我已将属性上的间距设置为0并检查/取消选中各种选项,但没有运气! 我已取消选中面板和按钮对象的Child Force Expand的宽度选项,但句子看起来很挤....我该如何确保按钮整齐地排列在彼此后面(即不重叠)?

enter image description here

以下是与下方评论相关的代码:

 for (int i = 0; i < letterArray.Length; i++)
        {
            button = (GameObject)Instantiate(buttonPrefab);
            button.transform.SetParent(buttonPanel.transform, false);
            button.GetComponentInChildren<Text>().text = letterArray[i];

            FitButtonWidthToText();
        }
    }

    public void FitButtonWidthToText()
    {
        int widthOfTheText = 0;
        CharacterInfo characterInfo;
        foreach (char c in button.GetComponentInChildren<Text>().text)
        {
            button.GetComponentInChildren<Text>().font.GetCharacterInfo(c, out characterInfo, button.GetComponentInChildren<Text>().fontSize);
            widthOfTheText += characterInfo.advance;
        }
        buttonTransform.sizeDelta = new Vector2(widthOfTheText, buttonTransform.sizeDelta.y);
    }
2个回答

5

取消选中Child Force Expand: Width

文档中获得:

Child Force Expand: 是否强制子布局元素扩展以填充额外的可用空间。

选择width(或height)将使元素水平(或垂直)地填充可用空间。


编辑:不要在Layout Group的子项上放置Content Size Fitter。 更多信息:调整UI元素大小以适应其内容

根据我们的讨论:因此,上面链接中描述的步骤仅适用于Unity最新版本。 如果您被困在一个更成熟的版本中,可以保持ContentSizeFitter以实现所需的结果,但请注意,如果更改子元素的大小,则布局不会自动更新,如您所预期的那样。 要解决此问题,您可以强制部分布局,如Stephan-B此线程中所解释的那样:

以下函数LayoutRebuilder.ForceRebuildLayoutImmediate应该很有用。 您可以在包含影响相关对象的布局组件的层次结构中的根(顶级父)对象上调用此函数,而不是强制重建所有可能对性能产生重大影响的画布。


哇,谢谢@hugo。只是想和你确认一下,在创建按钮本身(在“for”循环中)之后,我是否应立即调用LayoutRebuilder函数?调用会像这样吗?LayoutRebuilder.ForceRebuildLayoutImmediate(button.transform);我不确定作为函数参数传递什么...是按钮rect transform,因为它是文本组件的父级吗? - Lloyd
1
说实话,我没有使用过这种技术...我的方法可能有点粗糙,因为我不知道那个。但是首先尝试文本,然后是按钮,如果不起作用,再尝试布局。这样你就会知道最有效(可行!)的替代方案。 - hugo
@hugo,抱歉又来打扰你了!我不太确定方法调用如何适配我的脚本:/ 我今天尝试了一下,但好像什么都没发生……你有想法在哪里/如何调用它吗?我在原帖中附上了代码片段。我是否保留按钮的内容过滤器和水平组布局?我也会为父面板保留水平布局组吗? - Lloyd
首先,您能否通过编辑器进行微调(无需脚本)使按钮正确运作? - hugo
我可以让按钮出现并显示相应的文本,但是布局很混乱 :/ - Lloyd
显示剩余13条评论

1
你可以手动计算按钮的宽度,像这样。不要使用LayoutGroup来控制任何与宽度有关的内容。你可能想要添加一些额外的空间,因为按钮非常紧密地排列在一起,但我将其留给你:D
using UnityEngine;
using UnityEngine.UI;

//Just to make sure its put on a button
[RequireComponent(typeof(Button))]
public class FitButtonSizeToText : MonoBehaviour
{
    RectTransform buttonTransform;
    Text buttonText;

    void Awake() {
        buttonTransform = GetComponent<RectTransform>();
        buttonText = GetComponentInChildren<Text>();
    }

    void Start() {
        FitButtonWidthToText();
    }    

    public void FitButtonWidthToText() {
        int widthOfTheText= 0;
        CharacterInfo characterInfo;
        foreach(char c in buttonText.text) {
            buttonText.font.GetCharacterInfo(c, out characterInfo, buttonText.fontSize);
            widthOfTheText += characterInfo.advance;
        }
        buttonTransform.sizeDelta = new Vector2(widthOfTheText, buttonTransform.sizeDelta.y);
    }
}

谢谢你的代码。我刚刚将它实现到我的项目中,但好像没有任何作用...基本上,我最初是通过一个for循环创建我的按钮。然后在循环外部调用了你的方法。你觉得我这样做对吗? - Lloyd
脚本位于与按钮组件相同的游戏对象上的按钮预制体上吗?此外,按钮的父级应该有一个布局组(您可以启用除宽度相关之外的所有内容,这就是脚本的作用),但是父级、按钮或子级都不应该有内容大小适配器。 - yes
谢谢。嗯,我在ButtonPrefab下创建了一个脚本,将你的代码复制到其中,并确保按钮父对象有一个水平布局组(未选中宽度),但它没有起作用 :/ 是不是因为你的脚本在我的其他脚本有机会将文本填充到按钮之前就已经运行了? - Lloyd
我刚意识到,我把函数调用放在了 Awake 中,也许应该将其移动到 Start 中(我也会在答案中进行编辑),或者在设置文本后手动调用它。 - yes
啊,这个有点奇怪……不过还是感谢您的坚持!希望我们能尽快找到问题的根源 :) - Lloyd
显示剩余9条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接