Unity中使碰撞检测的碰撞箱处于不同层级的方法
Unity中使碰撞检测的碰撞箱处于不同层级的方法
- Unity在做碰撞检测时,Mono基类的碰撞与触发检测函数诸如OnCollisionEnter()之类必须得获取到与其代码附着地同层级的碰撞箱才能进行检测,当碰撞箱单独拎出来时,代码就不会工作了。
- 我被这狗屎问题困扰了多年,今天终于有了解决方案。
- 当然这个方法只是解决此问题的众多方法之一,成熟点的方法也许会用到接口与委托,这里我就使用我的方法。
(甲)物理碰撞的条件
- 达成物理碰撞有如下的条件:
- 碰撞物体双方都拥有碰撞箱(Collider抽象类及其子类)
- 碰撞物体至少有一方拥有刚体(Rigidbody类)
(乙)碰撞及触发检测方法
- 基础的碰撞检测方法如下:
- private void OnCollisionEnter(Collision collision)
- private void OnCollisionStay(Collision collision)
- private void OnCollisionExit(Collision collision)
- 基础的触发检测方法如下:
- private void OnTriggerEnter(Collider other)
- private void OnTriggerStay(Collider other)
- private void OnTriggerExit(Collider other)
(丙)使用代理碰撞器
- 首先需要一个基类,负责管理所有的碰撞事件,在此命名为
ObjectManager
1 | public class ObjectManager : MonoBehaviour |
- 再创建一个代理碰撞器类,代理碰撞器会代替基类去碰撞,在此命名为
CollisionProxy
1 | public class CollisionProxy : MonoBehaviour |
- 在代理器中加入需要代理的检测方法,注意代理器与基类都需要继承自
MonoBehaviour
1 | public class ObjectManager : MonoBehaviour |
- 代理器中还需要获取代理的基类以及自身的代理序号
1 | public ObjectManager objectManager;//代理器所代理的基类 |
- 在基类里定义与代理器中相对应的代理方法,需要在参数中传递碰撞信息与代理器自身
- 代理方法需要用
virtual
设置为虚拟方法,这样子类就能够用override
重写
1 | public class ObjectManager : MonoBehaviour |
- 加入用来调用测试的行
1 | public class ObjectManager : MonoBehaviour |
- 在代理器中调用此基类的代理方法,将信息传入
1 | public class CollisionProxy : MonoBehaviour |
- 回到Unity里,创建一个球,携带碰撞箱,在其身上加上刚体,勾去使用重力,勾选
Is Kinematic
,这个球就是需要被检测的对象 - 再新建一个方体,把碰撞箱移除,附上
ObjectManager
基类 - 在方体的子级里添加三个空物体,附上碰撞箱组件(这里是
Sphere Collider
),再附上CollisionProxy
代理器组件,将父级赋给代理器组件中的objectManager
参数,更改每一个代理器中的proxyIndex
序号 - 这里为了测试触发器,将代理器中的碰撞箱的
Is Trigger
勾上了
- 这时运行工程,手动移动方体的位置,使得子级代理器的碰撞箱触发球体
- 测试成功,基类获取到了触发信息(包括触发的物体、代理器序号的信息)
- 为了使得此方法变得更好用,这里定义一个新脚本来继承
ObjectManager
基类,在此命名为ObjectManagerSon
- 因为面向对象的多态特性,代理器组件所调用的基类函数会下达到其子类的重写函数,所以只需要在
ObjectManagerSon
中,重写代理碰撞方法,稍微对测试行进行修改
1 | public class ObjectManagerSon : ObjectManager |
- 将场景中方体身上的
ObjectManager
替换为子类ObjectManagerSon
,并赋给三个代理器的objectManager
参数
- 成功
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 Iamsleepingnow 世界!