我正在尝试复制塞尔达健康系统。代码看起来很好,工作正常。
但心脏容器放错了。它们在画布下面实例化。
这是重要的代码,心容器是正确的,只是在错误的位置。
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预制对象在画布下面实例化?
答案 0 :(得分:2)
我认为你得到的是这样的东西:
您可以通过将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定位位置的其他有用变量:
这些是anchoredPosition
,anchoredPosition3D
,anchorMax
和anchorMin
,可以修改为:
yourUIObj.GetComponent<RectTransform>().anchoredPosition = ...
yourUIObj.GetComponent<RectTransform>().anchoredPosition3D = ...
yourUIObj.GetComponent<RectTransform>().anchorMax = ...
yourUIObj.GetComponent<RectTransform>().anchorMin = ...