在我当前正在从事的项目中,我让用户单击一个区域,稍后将其放置在环境中。我想通过在画布上放置简单的标记来可视化它们放置的内容,以便在它们添加和删除点时标记也可以来回移动。
我已经找到了一些有关如何开始的资源,列出了如何将预制件实例化到画布中,但这似乎对我没有用。我觉得这一定与我使用坐标的方式有关,但我不确定。
public GameObject markerPrefab;
然后在另一个函数中
GameObject boatMarker = Instantiate(markerPrefab, Input.mousePosition, Quaternion.identity);
boatMarker.transform.SetParent(GameObject.FindGameObjectWithTag("Canvas").transform, false);
代码运行,并且预制件确实进入了场景,但是它们都出现在画布的右上角,一种在另一种之上。有任何想法我在这里做错了吗?另外,虽然我不想让你们为我编写代码,但对于以后如何删除预制件的特定实例有什么建议吗?
答案 0 :(得分:2)
我要说的主要问题是您正在使用带有第二个参数false
的{{3}}
如果使用
true
,则会修改父相对位置,比例和旋转,使对象保持与以前相同的世界空间位置,旋转和比例。
对于您而言,您想要保持相同的世界空间位置。
由于您的画布为Screenspace overlay
,因此其宽度和高度(以Unity单位为单位)与显示/窗口像素的宽度和高度完全匹配。因此,当您这样做
GameObject boatMarker = Instantiate(markerPrefab, Input.mousePosition, Quaternion.identity);
已经的对象处于正确的位置。为了直观地看到我只是给它一个立方体,所以您看到它在我单击的位置已经生成了(您看不到该图像,因为它不是Canvas的孩子):
如果将那个false
参数传递给SetParent
会发生什么,那就是它不会保留其当前的世界空间位置,而是保留其当前的localPosition并移至其父对象中的相对位置。由于它是Canvas
,而您的预制件也可能也使用RectTransform
,因此产生的位置取决于许多因素,例如预制RectTransform
的枢轴和锚点设置,例如Canvas Scaler
-> Scale Factor
。
如果您的预制件例如锚定在中心(通常是默认值)上,而您恰好单击窗口的中心,它将显示在右上角。
为什么?
您单击(windowWidth / 2, WindowHeight / 2)
。因此,预制件最初是在此处生成的
比起false
使用SetParent,它可以保持该位置,但是这次相对于Canvas的中心
=>画布位置的中心是(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
。我宁愿只获取一次,甚至在可能的情况下通过检查器进行引用:
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);
}
}
答案 1 :(得分:0)
尝试一下:
1-将按钮插入“画布”
2-获取此按钮的Gameobject参考
3-将按钮分配给button变量,将游戏画布分配给代码Canvas变量后,尝试此代码,它将正常工作
public GameObject refButton;
public GameObject canvas;
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
if (Input.GetMouseButtonDown(0))
{
GameObject button = Instantiate(refButton, Input.mousePosition,Quaternion.identity);
button.transform.SetParent(canvas.transform);
}
}