Основная проблема, которую я бы сказал, заключается в том, что вы используете SetParent
со вторым параметром false
Если true
, родительская относительная позиция, масштаб и вращение изменяются таким образом, что объект сохраняет то же положение в мировом пространстве , вращение и масштаб, что и раньше.
В вашем случае вы хотите сохраняйте то же положение в мировом пространстве.
Поскольку ваш холст Screenspace overlay
, его ширина и высота (в единицах Unity) точно соответствуют ширине и высоте пикселя дисплея / окна.Поэтому, когда вы делаете
GameObject boatMarker = Instantiate(markerPrefab, Input.mousePosition, Quaternion.identity);
Объект уже находится в в правильном положении.Чтобы представить, что я просто дал ему куб в качестве дочернего, чтобы вы увидели, что он появляется уже там, где я щелкнул (вы еще не видите изображение, потому что это не дочерний элемент Canvas):

Что произойдет, если вы передадите этот параметр false
в SetParent
, если он не сохранит свою текущую позицию в мировом пространстве, а вместо этого сохранит свою текущую локальную позицию и переместится в эту относительную позицию в пределахего родитель.Поскольку это Canvas
и ваш префаб, вероятно, также использует RectTransform
, результирующее положение зависит от многих вещей, например, от настроек поворота и привязки префаба RectTransform
, но также, например, от Canvas Scaler
-> Scale Factor
.
Если ваш префаб, например, закреплен в центре (обычно по умолчанию), и вы щелкаете точно по центру окна, он появится в правом верхнем углу.

Почему?
Вы нажимаете на (windowWidth / 2, WindowHeight / 2)
.Таким образом, здесь создается префаб
Чем вы используете SetParent с false
, так что он сохраняет эту позицию, но на этот раз относительно центра холста
=>Положение центра холста равно (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);
}
}
