UI预制件在画布下方实例化

时间:2017-06-28 12:07:07

标签: c# user-interface unity3d

我正在尝试复制塞尔达健康系统。代码看起来很好,工作正常。

但心脏容器放错了。它们在画布下面实例化。

这是重要的代码,心容器是正确的,只是在错误的位置。

x和y的计算是正确的,但在画布上却没有。

  private Transform healthBar = GameObject.FindGameObjectWithTag("HealthController").transform; // container for the heartContainers

    private GameObject healthWrapperObject = Resources.Load("HealthContainer") as GameObject; // the backgroundImage and parent of the heart

    private List<Image> healthContainers = new List<Image>(); // list of hearts for later usages

    private int maxHealth = 6;
    private int currentHealth;

    private int healthPerHealthContainer = 4; // 4 lifepoints per heart
    private int healthContainersPerRow = 5; // 5 hearts per row

    private int healthContainerStartPositionX = 0; // Healthbar starts at 0 on x
    private int healthContainerStartPositionY = 0; // Healthbar starts at 0 on y

    private int healthContainerSpacingX = 10; // horizontal spacing
    private int healthContainerSpacingY = -10; // vertical spacing

    private void Start()
    {
        currentHealth = maxHealth;
        InitializeHealthBar();
    }

    public void InitializeHealthBar()
    {
        int neededHealthContainers = maxHealth % healthPerHealthContainer == 0 ? maxHealth / healthPerHealthContainer : maxHealth / healthPerHealthContainer + 1; // Calculate the needed container count
        int counter = 0; // counts the hearts per row 
        int x = healthContainerStartPositionX; // horizontal position of the heartContainer
        int y = healthContainerStartPositionY; // vertical position of the heartContainer

        for (int i = 0; i < neededHealthContainers; i++)
        {
            counter++;

            if (counter >= healthContainersPerRow) // start a new line after 5 hearts per row
            {
                x = healthContainerStartPositionX; // move back to the left
                y += healthContainerSpacingY; // go for the next line
                counter = 0; // reset the counter
            }
            else
                x += healthContainerSpacingX; // place the new container right next to the previous

            Transform newHealthContainerTransform = Instantiate(healthWrapperObject, new Vector2(x, y), healthWrapperObject.transform.rotation).transform; // create the healthContainer parent / backgroundImage
            newHealthContainerTransform.SetParent(healthBar); // take the container and make it a child of the healthBar
            healthContainers.Add(newHealthContainerTransform.GetChild(0).GetComponent<Image>()); // get the heart of the heartContainer and add it to the heartList
        }
    }

我添加了healthBar,healthContainer / backgroundImage和heart(“healthfill”)的转换设置。

在所有3个元素上,我按下了Strg + Alt和Shift来锚定它们。

应将heartcontainter添加到健康栏中,心脏是心脏容器的一个孩子并且设置为伸展(它应该与其父项相同)

为什么UI预制对象在画布下面实例化?

Ingame

HealthBar

HealthContainer

HealthObjekt

1 个答案:

答案 0 :(得分:2)

我认为你得到的是这样的东西:

enter image description here

您可以通过将false传递给SetParent函数的第二个参数来解决此问题。通过这样做,您将使变换保持其本地方向而不是其全局方向。

简单地替换:

newHealthContainerTransform.SetParent(healthBar);

使用:

newHealthContainerTransform.SetParent(healthBar, false)

您还可以设置父对象,并使实例化的Object的Transform在Instantiate函数中保持其局部方向。这样做的唯一缺点是你现在必须在另一行代码中设置对象的位置而不是像以前那样设置Instantiate函数。

Transform newHealthContainerTransform = Instantiate(healthWrapperObject, healthBar, false).transform;
newHealthContainerTransform.GetComponent<RectTransform>().anchoredPosition3D = new Vector2(x, y);

移动UI对象时,您应修改RectTransform个变量而不是Transform个变量。

以下是确定UI定位位置的其他有用变量:

这些是anchoredPositionanchoredPosition3DanchorMaxanchorMin,可以修改为:

yourUIObj.GetComponent<RectTransform>().anchoredPosition = ...
yourUIObj.GetComponent<RectTransform>().anchoredPosition3D = ...
yourUIObj.GetComponent<RectTransform>().anchorMax = ...
yourUIObj.GetComponent<RectTransform>().anchorMin = ...