2

显示碰撞不一致的 gif:http: //imgur.com/QB4XOv0.gif

在我的 Unity2D 游戏中,我有一个弹弓(玩家)向墙上发射弹珠(想想Puzzle Bobble类型的益智射击游戏)。每个弹珠都是预制件的克隆,每个预制件都有一个带有IsKinematic的刚体以及一个带有OnTrigger的CircleCollider

当大理石与两个侧壁碰撞时,我使用OnTriggerEnter2D()并旋转角度,使其以一定角度从墙壁反弹。当大理石与顶壁碰撞时,它基本上会冻结,此时我移除了刚体组件并设置了一个“topObjects”标签。

当一个大理石与另一个大理石碰撞时,就会发生不一致。有时会调用触发函数,有时则不会。触发器似乎是随机且不可预测的。

这是我的 C# 代码,用于检测碰撞和随之而来的行为(附在弹珠上):

using UnityEngine;
using System.Collections;
using System.Collections.Generic;

public class RockMove : MonoBehaviour
{
    public float speed = 0.5f;
    private Vector2 direction = new Vector2(0, 1);

    // current angle
    private float currentAngleZ;
    // indendiary angle
    private float angleB;

    // rotation speed
    private float rot;

    // curving speed
    private float rotMod;

    // stops marble when collides with wall
    private bool IsMoving = true;


    void Start() {
    }

    void Update ()
    {

        if (IsMoving) {
            rot = RockSpawn.rot;

            currentAngleZ = transform.eulerAngles.z;

            rotMod = transform.position.x * -0.5f;
            // moves it forward + adds speed
            transform.Translate(direction * Time.deltaTime * speed, Space.Self);
            // curving
            transform.Rotate (0, 0, rotMod, Space.Self);
            if (transform.position.x >= 0) {
                // faster speed when near walls "gravity/magnetism"
                speed += transform.position.x * 8 * Time.deltaTime;
            }
            if (transform.position.x < 0) {
                // faster speed when near walls "gravity/magnetism"
                speed += transform.position.x * -8 * Time.deltaTime;
            }
        }
        else {
            // when object is stationary
            speed = 0;
        }
    }


    void OnTriggerEnter2D(Collider2D collider){

        // if collides with another marble

        if (collider.gameObject.tag == "topObjects" ) {
            // get rid of rigidbody
            // can't have 2 rigidbodies when 2 objects collide
            Destroy(rigidbody2D);
            // freeze movement
            IsMoving = false;

            Debug.Log ("you collided with a marble");

            // freeze rotation
            this.transform.Rotate (0, 0, 0, Space.Self);

            // assign the new tag
            this.tag = "topObjects";
        }
        else if(collider.name == "TopWall")
        {
            Destroy(rigidbody2D);
            IsMoving = false;

            Debug.Log ("you broke the fourth wall!");
            transform.Rotate (0, 0, 0);

            this.tag = "topObjects";
        }
        else {
            // bounce off walls
            currentAngleZ = transform.eulerAngles.z;
            angleB = 360 - (2 * currentAngleZ);
            transform.Rotate (0, 0, angleB);
        }
    }

}

更新:简单地将 Update() 函数更改为 FixedUpdate() 似乎使触发器更加一致,但是在检测方式上仍然存在不一致。

我测试了rigidbody2d.velocity、transform.position 和其他各种变换函数,但是Transform.Translate 产生了最好的结果,将它从墙上弹回,尽管理论上它只是将物体传送到一个新位置。

降低速度也完全不会影响一致性,改变圆形碰撞器的大小也不会影响。

4

3 回答 3

1

这里有两个明显的事情:

1.)你的游戏对象有一个 Rigidbody2D,所以你不应该通过变换来移动它,而是通过具有如下功能的刚体:

rigidbody2D.MovePosition()

rigidbody2D.MoveRotation()

只需在 Unity 文档中查找它们即可。

2.) 将所有这些放入

void FixedUpdate()
{
    ...
}

这是有关物理引擎的所有内容的地方。还有大量在线资源可供阅读:)

于 2014-09-30T21:16:04.857 回答
1

无论您是否使用物理,OnTriggerEnter2D 都应该始终如一地工作。

但是,如果一个游戏对象与另一个游戏对象保持联系,您只会得到一次标记 OnTriggerEnter,这是它们发生碰撞的第一刻。之后,您可以通过调用 OnTriggerStay 继续了解两个游戏对象是否仍在碰撞。

然后在它们停止碰撞后, OnTriggerEnter 将重置并在联系其他游戏对象时再次触发,即使它与之前碰撞的完全相同。你检查过这个吗?

希望它有所帮助,我会发表评论,但我没有足够的声望点,所以如果我不应该发表,抱歉。

于 2014-09-30T20:44:37.063 回答
-2

我的理解是运动学刚体不能在 2D 中碰撞。我还是很新,但我在一些我自己的问题的答案中发现了这一点。你应该更多地研究它。

于 2014-12-04T19:28:00.593 回答