Создание префабов для холста по координатам мыши - PullRequest
1 голос
/ 07 апреля 2019

В проекте, над которым я сейчас работаю, у меня есть пользователи, которые щелкают по области, где они хотят поместить вещи в окружающую среду позже.Я хотел бы визуализировать то, что они размещают, с помощью простых маркеров, размещенных на холсте, чтобы при добавлении и удалении точек маркеры также приходили и уходили.

Я нашел некоторые ресурсы о том, какначнем с перечисления, как создавать префабы на холсте, но мне кажется, что это никогда не работает.Я чувствую, что это как-то связано с тем, как я использую координаты, но я не совсем уверен.

public GameObject markerPrefab;

Затем в другой функции

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

Код запускаетсяи prefabs действительно появляются на сцене, но все они появляются в верхнем правом углу холста, все вроде одного поверх другого.Есть идеи, что я здесь не так сделал?Кроме того, хотя я не хочу просить вас, ребята, написать мой код для меня, есть ли какие-либо предложения по поводу того, как удалить конкретные экземпляры префаба в дальнейшем?

Ответы [ 2 ]

2 голосов
/ 12 апреля 2019

Основная проблема, которую я бы сказал, заключается в том, что вы используете SetParent со вторым параметром false

Если true, родительская относительная позиция, масштаб и вращение изменяются таким образом, что объект сохраняет то же положение в мировом пространстве , вращение и масштаб, что и раньше.

В вашем случае вы хотите сохраняйте то же положение в мировом пространстве.

Поскольку ваш холст Screenspace overlay, его ширина и высота (в единицах Unity) точно соответствуют ширине и высоте пикселя дисплея / окна.Поэтому, когда вы делаете

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

Объект уже находится в в правильном положении.Чтобы представить, что я просто дал ему куб в качестве дочернего, чтобы вы увидели, что он появляется уже там, где я щелкнул (вы еще не видите изображение, потому что это не дочерний элемент Canvas):

enter image description here

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

Если ваш префаб, например, закреплен в центре (обычно по умолчанию), и вы щелкаете точно по центру окна, он появится в правом верхнем углу.

enter image description here

Почему?

  1. Вы нажимаете на (windowWidth / 2, WindowHeight / 2).Таким образом, здесь создается префаб

  2. Чем вы используете SetParent с false, так что он сохраняет эту позицию, но на этот раз относительно центра холста

    =>Положение центра холста равно (windowWidth / 2, WindowHeight / 2), поэтому добавление локальных сборных координат (windowWidth / 2, WindowHeight / 2) приводит к конечной позиции (WindowWidth, WindowHeight) == в верхнем правом углу.


Так что вы можете исправитьчто либо сделав заготовку закрепленной в левом нижнем углу

enter image description here

или не передавайте 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);
    }
}

enter image description here

0 голосов
/ 07 апреля 2019

Попробуйте:
1- вставить кнопку в холст
2 - получить ссылку на Gameobject для этой кнопки
3 - попробуйте этот код после назначения вашей кнопки переменной кнопки, а Game Canvas - переменной кода 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);
        }
    }

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...