Unity检测碰撞,不使用IsTrigger的OnCollisionEnter2D方法

3
我正在尝试创建一个门户,可以将玩家从一端带到另一端。因此,如果玩家处于门户的50%位置,其另外50%将从另一端突出。
我使用了两个完全相同的预制角色和完全相同的组件。门户将仅使用这两个预制字符,而不会实例化新的克隆体。
下图描述了我正尝试在Collider盒中使用的内容以移动它们: Explanation 只是为了澄清,我正在使用OnCollisionEnter2D检测接触点,以确定玩家从哪一侧进入门户。如上图右侧所示,“进入”的那个人应该能够随时回头并且不被删除,同时在通过另一侧离开时仍然能够被删除。
但是,我在我的代码中遇到的问题是当IsTrigger为false时,OnCollisionEnter2D函数仅适用于工作。但是当IsTrigger为false时,我的角色无法穿过门户,并被推入地面并掉出地图。
我曾尝试使用Physics2D.IgnoreCollision,但似乎没有效果。
第二个被移动到退出门户的角色被弹出,而不是具有平滑的过渡。
public Transform PortalExit;
public CharacterController2D Player;

private GameObject Player1;
private CharacterController2D Player1Controller;
private Vector2 Player1Position;
private GameObject Player2;
private CharacterController2D Player2Controller;
private Vector2 Player2Position;

// Use this for initialization
void Start () {
    Player1 = GameObject.FindWithTag("Player1");
    Player1Controller = GameObject.FindWithTag("Player1").GetComponent<CharacterController2D>();
    Player1Position = Player1.transform.position;
    Player2 = GameObject.FindWithTag("Player2");
    Player2Controller = GameObject.FindWithTag("Player2").GetComponent<CharacterController2D>();
    Player2Position = Player2.transform.position;
}

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

}

void OnCollisionEnter2D (Collision2D collision) {

    Collider2D collider = collision.collider;

    if (collider.gameObject.tag == "Player1") {

        Vector3 contactPoint = collision.contacts[0].point;
        Vector3 center = collider.bounds.center;

        bool right = contactPoint.x > center.x;
        bool top = contactPoint.y > center.y;

        if (right) {
            // Physics2D.IgnoreCollision(GameObject.FindWithTag("Player1").GetComponent<Collider2D>(), GetComponent<Collider2D>());

            // change Player2's position into the other portal
            print("Hello!");
            Player2Position.x = 1.6f;
            Player2Position.y = PortalExit.position.y;
            Player2.transform.position = Player2Position;
        }

        if (!right) {
            print("Goodbye!");
            // puts Player1 into the detention center
            Player1Position.x = -5.55f;
            Player1Position.y = -6f;

            Player1.transform.position = Player1Position;
        }

    }

    if (collider.gameObject.tag == "Player2") {

        Vector3 contactPoint = collision.contacts[0].point;
        Vector3 center = collider.bounds.center;

        bool right = contactPoint.x > center.x;
        bool top = contactPoint.y > center.y;

        if (!right) {
            // change Player2's position into the other portal
            Player1Position.x = -3.6f;
            Player1Position.y = PortalExit.position.y;
            Player1.transform.position = Player1Position;
        }

        if (right) {
            // puts Player1 into the detention center
            Player2Position.x = -5.55f;
            Player2Position.y = -6f;

            Player2.transform.position = Player2Position;
        }

    }
}

我最近在我的赛车游戏中尝试使用2D边缘碰撞器来进行高速计时器的检查点和区段结束。它们非常准确,比我预期的要更准确得多。我以为它们会有隧道和错过高速交互的问题,但实际上并没有。它们可以像无限厚度的2D形状一样使用。这意味着您可以将它们用于角色的极端边缘,以确定他相对于门户的位置,并在完全穿过时发出信号,无论是向左还是向右。将它们垂直地附着在角色的边缘上。明白了吗? - Confused
@Confusde 抱歉,我不明白你在建议什么... - m_cht
我需要画一些图片...你能等一下吗?我将在接下来的几天里为我的项目做一些事情,所以将能够画出相当具体的东西。 - Confused
我的技能是隐形瞬移,其中一些效果需要同时出现在两个位置。粒子、拖尾效果、声音和其他元素需要在瞬移过程中继续存在,因为这是一个无缝的瞬移,玩家不应该察觉到。所以我们有着相似的需求,但出于完全不同的原因。 - Confused
好的!我非常高兴看到你的图片。 - m_cht
抱歉一直拖延。我会在一两天内回复这个问题... - Confused
1个回答

1
你有两个选项: 1. 将 isTrigger 更改为 false,然后从编辑器或脚本中将 Rigidbody2D 的 Body Type 从 Dynamic 更改为 Kinematic:
rb2d.bodyType = RigidbodyType2D.Kinematic;

通过这样做,刚体将停止对来自其他物体的重力或力的反应。然后,您可以使用OnCollisionEnter2D来检测碰撞事件,而不会出现问题。

2. 将isTrigger更改为true,将Rigidbody2DGravity Scale设置为0,以便它不会穿过地面。现在,您可以使用OnTriggerEnter2D检测触发器,并使用Physics2D.Raycast模拟检测点,因为OnTriggerEnter2D无法提供碰撞点:

void OnTriggerEnter2D(Collider2D collision)
{
    //Calculate layermask that excludes this GameObject we are raycasting from
    int layerMask = ~(1 << gameObject.layer);

    float distance = 100f;

    // Cast a ray straight down.
    RaycastHit2D hit = Physics2D.Raycast(transform.position, transform.forward, distance, layerMask);

    if (hit.collider != null)
    {
        Collider2D collider = hit.collider;

        Vector3 contactPoint = hit.point;
        Vector3 center = collider.bounds.center;


        //...........
    }
}

我建议你试试两种方法,看看哪一种更适合你。


非常感谢您的帮助!我尝试使用选项1。虽然检测点非常有效,但我的角色无法通过碰撞器。由于这是一个门户,我需要平稳的过渡,我的角色需要能够通过它。我还尝试使用选项2。由于我不确定它的作用,我直接将代码粘贴到我的脚本中,但if语句根本没有执行。但至少这个选项允许我的角色通过。 - m_cht

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