在某些情况下忽略与某些对象的碰撞


14

我正在Unity中制作赛车游戏。该车具有增压/硝基加电功能。在增强时,我不想与僵尸相撞,但我确实想与墙壁相撞。

另一方面,我不想忽略与僵尸的碰撞,因为我仍然想对它们进行撞击。

我该如何处理?基本上,我想要的是汽车与某些物体碰撞时不要旋转。

Answers:


7

考虑在运行时操作图层。

为某些对象与整个图层启用/禁用碰撞

Physics.IgnoreCollisionPhysics.IgnoreLayerCollision允许您分别禁用两个碰撞器之间以及两个图层之间的碰撞。

如果要从碰撞中排除特定的对撞机,则没有内置的方法可以做到。如果您将非运动刚体与非触发对撞机配合使用,即使您尝试按标签过滤出响应,也始终会有响应。

我们在项目上完成此操作的方法是创建一个名为“ Void”的层。虚空根本不会与任何物体碰撞。

现在,您可以通过将碰撞器的图层设置为“ Void”来暂时禁用碰撞器,并通过恢复其旧图层来重新启用它。

这是要点:

int oldLayer = -1;
int voidLayer;

void Start()
{
    voidLayer = LayerMask.NameToLayer("Void");
}

void DisableCollider(Collider col)
{
    oldLayer = col.gameObject.layer;
    col.gameObject.layer = voidLayer;
}

void EnableCollider(Collider col)
{
    col.gameObject.layer = oldLayer;
}

我们之所以这样做,是因为在某些情况下启用和禁用刚体刚体的对撞机确实会搞砸事情。因此,您不能可靠地禁用复合刚体对撞机的一部分,但是可以可靠地在复合对撞机零件之一的层周围进行交换。

现在你的具体情况

为了减少僵尸碰撞对汽车的影响,请考虑使僵尸的运动刚度触发器成为可能,或者使它们的质量非常小(例如float.Epsilon),因此对汽车的动量的影响为零。发生碰撞时,您也可以进行此层切换,这样即使第一个碰撞对车身施加的作用力微不足道,也不会触发后续碰撞。

您甚至可以将它们切换到不与汽车碰撞的图层。

您还可以在僵尸上放置另一个对撞机,并在冲撞时激活它。这样,您可以伪造冲击力OnTriggerEnter。您可能无法获得如此精确的结果,但是您可以估算出接触法线足以将僵尸扔到有趣的地方的地方。

您必须问自己:

  • 我是否希望能够用我的车撞过去的僵尸,还是应该只播放死亡动画?

  • 我是否在乎撞僵尸是否会以较小的方式影响汽车的速度和角速度?


1

当汽车开始加速时,在所有僵尸上调用Physics.IgnoreCollision,同时将播放器对象的函数传递给该对象。这将导致Unity对播放器和僵尸之间的任何碰撞均不做出反应。当汽车完成助推时,Physics.IgnoreCollision再次呼叫每个僵尸,将玩家对象传递给它false,并使碰撞响应重新开始。


但这将意味着它们也不会与其他任何碰撞。
保罗·曼塔

我会做更多的研究。我唯一想到的是:也许您可以通过从OnCollisionEnter返回false来忽略冲突?
Wackidev

@Wackidev事实并非如此。
Rhys van der Waerden'7年

@Paul我已经编辑了答案。
Wackidev

0

我猜您可以检查对象的名称,或向对象类添加名称值,然后检查吗?

bool boosting = false; //need a trigger in the game to set this to true.

function OnCollisionEnter(theCollision : Collision)
{   
    if (boosting == true)
    {
        if(theCollision.gameObject.name == "Zombie")
        {
              Debug.Log("Zombie hit during boost");              
        }
        else if(theCollision.gameObject.name == "Wall")
        {
              Debug.Log("Wall hit during boost");            
        }
    }
    else 
    {
        if(theCollision.gameObject.name == "Zombie")
        {
              Debug.Log("Zombie hit not in boost");              
        }
        else if(theCollision.gameObject.name == "Wall")
        {
              Debug.Log("Wall hit not in boost");                
        }
    }
}

然后只有另一个变量,您可以使用它检查提升并将其添加到检查中。

编辑:添加此变量。


他知道如何通知碰撞。他只是不想采取任何行动。他想在某些情况下禁用内置的碰撞响应。
Wackidev

当然,触发碰撞时发生的一切发生在括号之间吗?我以前没有使用过unity,所以我不知道,但在cocos2d中,XNA就是这样。
刘易斯

实际上,Unity通过PhysX自行处理冲突。OnCollisionEnter只是一种通知方法;它并非旨在处理实际的碰撞响应。
Wackidev'7

0

我假设您正在使用物理引擎根据物体碰撞时的形状/质量自动进行“偏离”?如果是这种情况,则将僵尸的质量更改为非常小的值,它们不会影响汽车。


0

这里有两类答案:

  1. 忽略或禁用碰撞
    • 这些解决方案无法解决问题,他希望僵尸在被击中时能够飞行。
  2. 改变质量:
    • 这是一个好方法。别忘了还要相应地改变惯性。
      • 您也可以在助力时改变汽车的质量和惯性(这样做是为了减少助力时所有非运动物体对汽车的影响)
      • 假定这是运动学的,则这不应影响道路或墙壁。

希望这可以帮助!


六年前已有的两个答案已经建议您在此处建议的基于质量的方法。您要添加一些新策略吗?
DMGregory

抱歉,我还不能投票,我想确保Paul Manta不会误入歧途。
dwuLive
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.