在没有IsTrigger的情况下使用OnCollisionEnter2D统一检测冲突

时间:2018-11-06 04:45:52

标签: c# unity3d 2d

我正在尝试创建一个可以将玩家从一端带到另一端的门户。因此,如果玩家从另一端进入门户网站有50%,那么他的另外50%将从另一端伸出。

我正在使用两个完全相同的精灵和完全相同的组件的预制角色。这些门户将仅使用这两个预制角色,而不是证实新的克隆体。

下图描述了我要对撞机盒进行移动以进行的操作: Explanation

请澄清一下,我正在使用OnCollisionEnter2D来检测接触点,以确定玩家从哪个方向进入门户。如上图的右侧所示,“家伙进入”应该能够随时转回并且不会被移走,而当他从另一边离开时仍然能够被移走。

但是,我的代码面临的问题是OnCollisionEnter2D函数仅在IsTrigger为false时才起作用。但是当IsTrigger为假时,我的角色将无法通过门户并被推入地面并掉落在地图上。

我尝试使用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;
        }

    }
}

1 个答案:

答案 0 :(得分:1)

您有两个选择:

1 。将isTrigger更改为 false ,然后从编辑器或通过脚本将Rigidbody2D主体类型从动态更改为运动:

rb2d.bodyType = RigidbodyType2D.Kinematic;

这样做,刚体将停止对重力或来自其他物体的力产生反作用。然后,您可以使用OnCollisionEnter2D来检测碰撞事件,而不会遇到问题中描述的问题。


2 。将isTrigger更改为 true ,将Rigidbody2D Gravity 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;


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

我建议您同时尝试这两种方法,然后看看您最喜欢哪一种。