如果两个对象交互,则保存交互代码的是什么?


28

想想子弹和敌人,或者玩家和地板。如果这些对象进行交互,那么交互代码将由什么保存?


2
以什么方式互动?您是指碰撞检测吗?如果是这样,那么您很有可能同时实现冲突检测类和冲突解决管理器。
CaptainRedmuff

从某种程度上来说,我对碰撞以及碰撞后发生的事情都感兴趣。子弹会检查它是否靠近敌人,或者反过来吗?碰撞后会发生什么,子弹物体能否告诉敌人物体被击中?如您所见,我对整个事情感到很困惑,这使某些代码很难阅读。
ThatOneGuy 2013年

Answers:


23

TL; DR:

您的游戏对象彼此之间不认识,也不对其他对象执行检查。您将创建一个碰撞检测和碰撞解决方案模式,该模式可以检查您的游戏对象并执行适当的操作来模拟游戏物理。

好东西

从先前编写冲突检测和阅读本书的尝试开始,冲突检测和冲突解决分为两个阶段。第一阶段(碰撞检测)是一个提前通过的过程,您可以在该过程中确定两个对象是否可能存在潜在的碰撞。如果任何两个对象形成潜在的冲突,则将这些对象传递到第二阶段(冲突解决方案),以对这些对象进行更细粒度的检查,并尝试解决该冲突。

在引擎/游戏中的某个位置,您将拥有世界上所有对象的数组。在每一帧上,您都将遍历数组,并通过简单的边界框/球体碰撞检测将每个对象与其他每个对象进行检查。

伪代码:

dectectCollisions(objects)
{
    for(objectA in objects)
    {
        for(objectB in objects)
        {
            if(objectA != objectB) //ignore self
            {
                if(BoundingSpheresIntersect(objectA, objectB))
                {
                    collisionResolver.addObjects(objectA, objectB);
                }
            }
        }
    }
}

这种循环效率不高,但是通过使用空间分区作为保证对象相距太远而不会发生碰撞的对象的提早工作,确实留下了改进的空间。

在检查了两个对象的潜在碰撞之后(即,两个对象都足够靠近以至于发生碰撞),将这些对象放下以执行更精确的碰撞检测例程。

想象一下,您有两个形状和大小随机的多边形,这些多边形足够接近以至于可能相交,但由于其几何形状而并非如此:

Image found via google

使用边界球,这两个对象将为潜在碰撞创建假阳性。然后,您可以在此处执行更彻底的遍历,以确定两个对象是否确实相交。

找到真正的碰撞后,您的碰撞解决步骤将执行适当的操作,以根据游戏物理的粒度和需求,通过施加力或力矩来解析对象。

考虑到这一点,您可以抽象出碰撞检测和解决过程的整个过程,这样您的对象就不需要了解彼此,也不需要了解确定和解决碰撞的过程。为您处理此问题的两个类/管理器只需要了解每个对象的基本属性,即可对冲突进行快速而肮脏的检查,然后需要进行更彻底的检查。


2
尤其是,中介器设计模式将是适当的。观察者模式将是一个很好的选择,它具有非常不同的意图。您可以在此Stackoverflow帖子中获得有关它们的很好的总结。
kurtzbot

12

虚幻引擎3处理它的一种方式:

子弹会收到一条碰撞消息,说它撞到了东西,并有一个参数告诉它撞到了什么。然后可以调用objectHit.takeDamage(self)。然后目标获得TakeDamage消息以及指向命中目标的指针,并采取适当的措施。

我个人喜欢这种方法,因为这意味着子弹可以采取特殊的动作(例如根据所击中的东西的类型产生某种爆炸效果),而目标可以根据子弹的类型采取特殊的动作。

子弹也可能知道它对目标的作用,并可以在其上调用函数,例如objectHit.freeze(self)。然后目标知道它被冻结的东西击中了,那是什么样的物体。

编辑:此答案是作为它如何工作的一般图片,因为您可能不使用UE3。:)


10

小偷在带有来源和接收器的黑暗引擎中做得很好。一个对象可能具有这两种属性,并且具有不同的类型。例如,“水”箭头在接触时将具有“水刺激”的源。爆炸将产生AoE FireStim。

当“水箭”击中一个对象时,目标对象会在其接收器中搜索任何寻找具有适当强度值的“水刺激”的对象。然后,它执行与之相关的任何命令(在这种情况下,将燃烧的火炬转换为割炬,并散发出烟。)

由于在SystemShock2中使用了相同的引擎,这就是处理所有不同伤害类型的方式,不同的子弹具有不同的刺激设置,然后不同的怪物针对不同的刺激类型具有接收器,并且造成的伤害等于1 *,2 *,1 / 2强度取决于弹药类型是否“超级有效”。

这似乎是一个非常灵活的系统,因为您可以在关卡编辑器中向对象添加源和接收器(例如,使一扇门被大火击中时打开。)同时您还可以告诉接收器“发送脚本”消息”(如果对象具有与之关联的特殊脚本)。

您不想做的是必须对所有可能的对象与所有可能的对象发生碰撞的nXn交互矩阵进行硬编码!通过标准化消息对交互进行概括,可以简化流程。


从脚本的角度来看,这种方法似乎是最灵活和最具表现力的。很酷。
drhayes 2013年

-2

一种解决方案是将子弹和玩家的容器放在单独的类中,然后具有main()函数,使框架循环负责交互。

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.