OnGUI和协程移动对象:确实很奇怪的行为

时间:2019-05-15 22:59:42

标签: c# unity3d

在标题中以最佳方式概括此行为并不容易。 我有一个编辑器和在[ExecuteInEditMode]中执行的Monobehaviour。 我需要通过使用鼠标选择对象来移动它们。我以为我既可以使用角色也可以使用精灵来执行此操作,所以我没有遇到任何困难。但是我错了。当我选择一个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);
}

我使用两个公共变量简化了所有操作,以选择要移动的对象。 我所做的非常简单,我不明白为什么会出现这种行为。有了角色,我没有问题(即使是精灵,现在我也从代码中删除了它也没有问题)。当我用鼠标右键单击时,我将运行协程,该协程会将字符移动到光标坐标,然后像这样继续直到释放按钮。没问题,字符随光标移动而没有问题。 但是,如果我对Sphere,Cylinder,Cube等3D对象执行相同的操作(向左按钮),则它会跟随鼠标移动,但是如果我不移动光标并且不释放按钮,则该对象会随着Y滑离Z轴负向增加。如我所说,如果禁用碰撞器,则对象将保持在光标位置。 问题在于无法通过公共变量选择球体,而是直接从脚本中选择球体,因此我需要对撞机。 我可能不太了解Unity,无法了解这种行为的原因。 你能为我澄清一下吗?

1 个答案:

答案 0 :(得分:2)

OnGui不好(让我解释一下)

首先,OnGui是Unity IMGui系统(代表IMmediate Gui)的一部分,由于支持uGui而大幅贬值,由于很多原因,使用uGui更加容易。这些原因之一是...。

每帧

OnGui被调用多次

因为OnGui每帧被多次调用,这意味着Event.current不变,意味着moveChar不变,这意味着协程开始不止一次。 / p>

这没有真正的解决方法。使用OnGui几乎不可能完成您想要的事情。从来都不打算处理这种逻辑。

您应该做的所有事情都放在Update()内部,例如用他们的e.rawType == EventType.MouseDown亲戚代替Input之类的东西。 Input.GetMouseDown(0)