首页 > 解决方案 > 在鼠标坐标处将预制件实例化为画布

问题描述

在我目前正在进行的一个项目中,我让用户单击一个区域,以便他们稍后将事物放入环境中。我想通过放置在画布上的简单标记来可视化他们放置的内容,这样当他们添加和删除点时,标记也会来来去去。

我找到了一些关于如何开始的资源,列出了如何将预制件实例化到画布中,但它似乎对我不起作用。我觉得这一定与我使用坐标的方式有关,但我不完全确定。

public GameObject markerPrefab;

然后在另一个函数中

GameObject boatMarker = Instantiate(markerPrefab, Input.mousePosition, Quaternion.identity);
boatMarker.transform.SetParent(GameObject.FindGameObjectWithTag("Canvas").transform, false);

代码运行,预制件确实生成到场景中,但它们都出现在画布的右上角,都是一个在另一个之上。有什么想法我在这里做错了吗?另外,虽然我不想让你们为我编写代码,但是关于如何在以后删除预制件的特定实例的跳跃点有什么建议吗?

标签: c#unity3d

解决方案


我要说的主要问题是您使用SetParent的是第二个参数false

如果true,则修改父相对位置、比例和旋转,以使对象保持与以前相同的世界空间位置、旋转和比例。

在您的情况下,您希望保持相同的世界空间位置。

由于您的画布Screenspace overlay的宽度和高度(以 Unity 为单位)与显示/窗口像素的宽度和高度完全匹配。因此,当你这样做

GameObject boatMarker = Instantiate(markerPrefab, Input.mousePosition, Quaternion.identity);

对象已经正确的位置。想象一下我只是给了它一个立方体作为孩子,所以你看到它已经在我点击的地方产生了(你看不到图像,因为它不是 Canvas 的孩子):

在此处输入图像描述

如果将该false参数传递给会发生什么SetParent,它不会保持其当前的世界空间位置,而是保持其当前的 localPosition 并移动到其父级中的该相对位置。由于它是 aCanvas并且您的预制件可能也使用 a结果RectTransform位置取决于很多事情,例如预制件的枢轴和锚点设置,以及-> 。RectTransformCanvas ScalerScale Factor

如果您的预制件例如锚定在中心(通常是默认设置)并且您准确地单击窗口的中心,它将出现在右上角。

在此处输入图像描述

为什么?

  1. 你点击(windowWidth / 2, WindowHeight / 2)。所以预制件最初是在这里产生的

  2. 比你使用 SetParentfalse所以它保持那个位置,但这次是相对于画布的中心

    => 画布位置的中心(windowWidth / 2, WindowHeight / 2)因此添加本地预制坐标(windowWidth / 2, WindowHeight / 2)会导致最终位置(WindowWidth, WindowHeight)== 右上角。


所以你可以通过将预制件固定在左下角来解决这个问题

在此处输入图像描述

或不false作为参数传递给SetParent.

boatMarker.transform.SetParent(_canvas.transform);

您实际上也可以在一个电话中完成

Instantiate(markerPrefab, Input.mousePosition, Quaternion.identity, _canvas.transform);

此外,您不应该FindObjectWidthTag一次又一次地使用。如果可能的话,我宁愿只得到一次,甚至通过 Inspector 引用它:

public GameObject markerPrefab;

[SerializeField] private Canvas _canvas;

private void Awake()
{
    // If no canvas is provided get it by tag
    if (!_canvas) _canvas = GameObject.FindGameObjectWithTag("Canvas").GetComponent<Canvas>();
}

// Update is called once per frame
private void Update()
{
    if (Input.GetMouseButtonDown(0))
    {
       Instantiate(markerPrefab, Input.mousePosition, Quaternion.identity, _canvas.transform);
    }
}

在此处输入图像描述


推荐阅读