Unity中的2D传送门有时无法正常工作

3
我正在尝试在Unity中创建一个2D传送门,不仅可以将玩家传送到另一个传送门游戏对象中,还可以保持玩家通过传送门后的位置、移动方向和速度。
我并不是个艺术家,但举个例子: enter image description here 玩家是一个在区域内弹跳的球,当他穿过门时,他的速度保持不变,并且他进入了传送门的中心。
例如在这里: enter image description here 如果玩家进入传送门的下半部分,他将从传送门的下半部分出来。
当这个系统工作时,它非常好用!然而,它只有50%的时间能正常工作,这50%的问题可能会有很多不同的问题,有时球会无法传送。有时球击中第一个传送门,传送到第二个传送门,然后返回到第一个传送门,一直反复进行。而且它似乎也是随机出现这些问题。
这是我的脚本:
public GameObject otherPortal;
    public PortalController otherPortalScript;
    private BallController ballController;
    public float waitTime = 0.5f;

    [HideInInspector]
    public bool teleporting;

    // Use this for initialization
    void Start () 
    {

    }

    // Update is called once per frame
    void Update () 
    {

    }

    void OnTriggerEnter2D(Collider2D other)
    {
        if (other.gameObject.tag == "Ball")
        {
            ballController = other.GetComponent<BallController>();
            if(!teleporting)
            {
                var offset = other.transform.position - transform.position;
                offset.x = 0;
                other.transform.position = otherPortal.transform.position + offset;
                otherPortalScript.teleporting = true;
                teleporting = true;
                StartCoroutine("Teleport");
            }            
        }
    }

    void OnTriggerExit2D(Collider2D other)
    {
        if (other.gameObject.tag == "Ball")
        {
            teleporting = false;
            otherPortalScript.teleporting = false;
        }

    }

    IEnumerator Teleport()
    {
        yield return new WaitForSeconds(waitTime);
        teleporting = false;
        otherPortalScript.teleporting = false;
        ballController.teleporting = false;
    }
}

该脚本附加在两个门户上,它们都是同一对象的预制体。我在编辑器中设置了“otherPortal”、“otherPortalScript”和“waitTime”。其中,“waitTime”是我事后添加的,用于解决另一个问题,即有时“传送”永远不会被设置为false。我认为这个问题的原因与那个问题相同,因此“waitTime”只是对更大问题的临时解决方案。此外,每当Portal脚本更改“ballController”中的变量(例如“ballController.teleporting=false;”)时,仅因为球正在向得分系统添加或删除点数,它根本不会影响球的运动。


1
看看这个编程冒险视频,他详细介绍了在制作门户时遇到的所有错误。我相信他遇到的问题与你自己遇到的问题非常相似,如果不是完全一样的话。 - GTBebbo
由于浮点误差,我们可以将传送门看作具有厚度,并意识到触碰传送门是与完全位于其一侧不同的状态。 - Leo Bartkus
@GTBebbo 我可能错了,但是看完视频后,它似乎只解释了视觉门户幻象的困难,我的门户是2D的,不需要那种幻象,因为玩家不需要通过另一个门户来查看。我错过了什么吗? - Jhon Piper
@LeoBartkus 这是一个很好的观点,你会如何来反驳它? - Jhon Piper
如果我没记错的话,他会像LeoBartkus建议的那样扩展门户的厚度来处理不总是传送的问题。但很抱歉,我误读了原帖,没有意识到它只是2D。 - GTBebbo
1个回答

1
考虑取消传送门和球的teleporting属性以及waitTime。现在给球一个List<PortalController> inUseControllers(请注意,您需要添加using System.Collections.Generic)。每当它进入一个传送门时,请检查列表是否为空,通过使用inUseControllers.Count == 0进行检查,如果是,则将两个涉及的PortalController添加到该列表中并处理传送运动。当球离开一个PortalController时,从inUseControllers列表中删除它;因此,只有当球离开每个传送门区域时,它才会再次清空。这种方法应该简化代码,同时安全地防止意外的来回循环。

好的,作为一名新手程序员,我从未以那种方式处理过列表,我很难弄清楚当你说“将两个涉及的PortalController添加到该列表中”时应该把东西放在哪里。你能给我一个更详细的例子来说明如何完成这个操作吗? - Jhon Piper
要将它们添加到列表中,请使用例如 inUseControllers.Add(this);(如果您在其中一个 PortalController 类中),然后是 inUseControllers.Add(otherPortalScript);。请确保已经通过 List<PortalController> inUseControllers = new List<PortalController>(); 在顶部创建了一次。祝你好运! - Philipp Lenssen
感谢回复,我已经删除了 teleportwaitTime 函数,并用列表进行了替换,现在看起来像这样:https://pastebin.com/Nckgbp7i 使用列表消除了球无法传送的问题;并将立即传送回来的问题减少到约10%。但是这10%仍然是一个问题。您知道那10%的原因吗? - Jhon Piper

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接