OnGUI и Coroutine перемещают объект: действительно странное поведение - PullRequest
1 голос
/ 16 мая 2019

В названии нелегко обобщить это поведение наилучшим образом.У меня есть редактор и Monobehaviour, выполненный в [ExecuteInEditMode].Мне нужно перемещать объекты, выделяя их мышью.Я думал, что не столкнулся с какими-либо трудностями, поскольку выполняю эту операцию как с персонажем, так и со спрайтом.Но я был неправ.Когда я выбираю 3D-объект (а не персонажа), я могу выбрать и перетащить его, но если я удерживаю кнопку мыши, не перемещая ее, она имеет тенденцию соскальзывать, как будто он падает, но по осям Y и Z.Если я отменяю выбор коллайдера, проблема не возникает, но очевидно, что коллайдер необходим для моих операций.Я удалил все ненужные строки из кода, надеясь решить проблему, но она остается.

    void OnGUI() {
    if (moveChar) {
        StartCoroutine("WaitChar");
    } else if (moveSpot) {
        StartCoroutine("WaitSpot");
    }
    Event e = Event.current;
    Vector3 mousePosition = e.mousePosition;
    mousePosition.y = Screen.height - mousePosition.y;
    Ray ray = cam.ScreenPointToRay(mousePosition);
    RaycastHit hitInfo;
    if (Physics.Raycast(ray, out hitInfo)) {
        mousePositionWorld = hitInfo.point;
        if (e.rawType == EventType.MouseDown) {
            switch (e.button) {
                case 0: 
                    if (isSelectedSphere) {
                        moveSpot = true;
                    } 
                    break;
                case 1:
                    if (isSelectedChar) {
                        moveChar = true;
                    } 
                    break;
            }
        } else if (e.rawType == EventType.MouseUp) {
            switch (e.button) {
                case 0: 
                    if (moveSpot) {
                        moveSpot = false;
                    } 
                    break;
                case 1:
                    if (moveChar) {
                        moveChar = false;
                    }
                    break;
            }
        }
    }
}

public IEnumerator WaitChar() {
    character.transform.position = mousePositionWorld;
    yield return new WaitForSeconds(0.1f);
}

public IEnumerator WaitSpot() {
    MoveSpot.transform.position = mousePositionWorld;
    MoveSpot.transform.localScale = Vector3.one * ((new Plane(cam.transform.forward, 
                                                    cam.transform.position).GetDistanceToPoint(
                                                    MoveSpot.transform.position)) / radiusPoint);
    yield return new WaitForSeconds(0.1f);
}

Я упростил все с помощью двух открытых переменных, чтобы выбрать объект для перемещения.То, что я делаю, очень просто, я не понимаю, почему у меня такое поведение.С персонажем у меня проблем нет (даже со спрайтами, которые на данный момент я убрал из кода).Когда я щелкаю правой кнопкой мыши, я запускаю сопрограмму, которая перемещает символ к координатам курсора и продолжается до тех пор, пока я не отпущу кнопку.Нет проблем, персонаж движется вместе с курсором без проблем.Однако, если я выполняю ту же операцию (левая кнопка) с трехмерным объектом, таким как Сфера, Цилиндр, Куб, он перемещается вслед за мышью, но если я не перемещаю курсор и не отпускаю кнопку, объект смещается вместе с Yи оси Z, которые увеличиваются отрицательно.Как я уже сказал, если я отключу коллайдер, объект останется в позиции курсора.Проблема в том, что сферы не могут быть выбраны через открытые переменные, а напрямую из скрипта, поэтому мне нужен коллайдер.Я, наверное, недостаточно хорошо знаю Unity, чтобы понять причину такого поведения.Можете ли вы уточнить это для меня?

1 Ответ

2 голосов
/ 16 мая 2019

OnGui плохо (позвольте мне объяснить)

Во-первых, OnGui является частью системы Unity IMGui (расшифровывается как IMmediate Gui), и его сильно обесценили в пользу uGui, с которым намного проще работать по ряду причин. И одна из этих причин ....

OnGui вызывается более одного раза за кадр

Поскольку OnGui вызывается несколько раз за кадр, это означает, что Event.current не изменился, что означает, что moveChar не изменилось, то есть ваша сопрограмма запускается более одного раза.

И нет никакого реального способа обойти это. Практически невозможно сделать то, что вы хотите, используя OnGui. Он никогда не предназначался для обработки подобной логики.

Все, что у вас есть, должно быть сделано внутри Update() и заменять такие вещи, как e.rawType == EventType.MouseDown, их Input родственниками, например. Input.GetMouseDown(0).

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