首页 > Unity3D频道 > 【Unity2D研究院之游戏开发】 > Unity2D研究院之精灵Sprite之间的碰撞事件(三)
2014
10-17

Unity2D研究院之精灵Sprite之间的碰撞事件(三)

碰撞我个人觉得可以分为两大类: 比较物理的碰撞,和不太物理的碰撞。

比较物理的碰撞:比如奋斗的小鸟这种游戏,小鸟飞出去后会根据自己的速度还有重力碰到障碍物后可能会被弹回来。

不太物理的碰撞:比如超级玛丽这种游戏,无论玛丽以多块的加速度向前跑碰到了障碍物,玛丽并不会被弹回来。

那么这篇文章我主要想写写 不太物理的碰撞,想一想以前的2D游戏是怎么做的?

场景层:场景编辑器来生成一个庞大的二维数组,每一个数字代表一个含义,比如0-9表示不同的tile(小图)。整个游戏场景都是根据二维数组用双for循环绘制出来的。

物理层:再来一个和上面一样的二位数组,比如0表示可以通过,1表示不可以通过,也就是碰撞层。 策划在编辑器里面来编辑所有的物理层。

有可能还会在有两个相同的二维数组, 前景层 后景层。。。就不赘述了。。 最后用代码去检测人物是否能继续前进,或者被碰撞。

结合到unity3d里面,现在还能这么搞吗?答案:当然能这么搞了,只是unity给我们提供了新的方案,检测碰撞的这一部分可以不用我们自己写代码了。。

二维数组似乎有点麻烦,我们把问题简化一下。如下图所示,红色区域表示小鱼不可行走区域。我相信刚开始学unity2d的人首先想到的就是transfom.postion 来给小鱼赋值, 在Update里面来检查是否碰撞,因为我也是这么想的。

Unity2D研究院之精灵Sprite之间的碰撞事件(三) - 雨松MOMO程序研究院 - 1

算法说难也不难,有轮子为什么我们不用呢?在处理位置的时候我们使用rigidbody2D.MovePosition()这个方法。另外记得要给精灵添加一个Rigidbody2D的组件。

如下图所示,小鱼在移动的时候,如果碰到的障碍物它就会停住。

Unity2D研究院之精灵Sprite之间的碰撞事件(三) - 雨松MOMO程序研究院 - 2

 

物理碰撞

如果需要精灵响应物理碰撞,那么就必须添加Rigidbody2D的组件。如下图所示,我不需要 位置与旋转运动阻力,所以linear Drag 和 angular Drag 设置0。我也不需要重力所以GravityScale 也就是0.我需要固定精灵的角度所以勾选Fixed Angle 。因为我需要感应物理碰撞,所以不够选Is Kinematic 。下面依次是物理差值、休眠模式、碰撞检测。调一调参数就能看出效果。

Unity2D研究院之精灵Sprite之间的碰撞事件(三) - 雨松MOMO程序研究院 - 3

这里我想详细的在说说 Is Kinematic 属性。既然已经需要用到物理碰撞,那么在勾选 Is Kinematic 是不是吃饱了撑了?我在做个假设?比如我现在控制小鱼在吃金币,当碰撞到金币的时候我并不希望小鱼停住。但是我程序中还想得到碰撞的这个事件,那么此时该如何? 解决这个命题之前我们要看看物理碰撞的事件。

物理碰撞的事件

这是要把碰撞的信息回调到代码中,以前物理老师讲过“力的作用是相互的”。“小鱼”碰撞“石头”也就是“石头”碰撞“小鱼”,那么Rigidbody2D组件到底是给“小鱼”加 还是给“石头”加?请记住一点,Rigidbody2D永远给需要感应物理(有位移)的对象加。

例子1:“小鱼”碰撞“石头” ,石头是要挡住小鱼的前进,那么石头永远不可能发生位移,Rigidbody2D加给小鱼。

例子2:“小鱼”要吃一个金币,但是金币被一个特殊的石头挡住了。我需要控制小鱼把这个石头挪开,因为这个石头需要发生位移,Rigidbody2D加给小鱼,并且加给石头。

例子3:“小鱼”不加Rigidbody2D 而“石头”加Rigidbody2D 这种情况应该是非常非常少见的。

回到物理的碰撞事件上,要得到精灵的碰撞事件,必须保证这两个精灵至少有一个含有Rigidbody2D组件。还是“小鱼”碰撞“石头”的例子。如下代码所示,“小鱼”和“石头”都挂上,当发生碰撞的时候都可以收到对方的信息。

OnCollisionEnter2D 表示进入碰撞的事件,对应还有碰撞中、和碰撞结束的事件。 详细的就在API里面找找吧。http://docs.unity3d.com/ScriptReference/MonoBehaviour.html显然这个脚本只挂在”小鱼”身上比较好,原因是可能有很多石头,只监听“小鱼”身上的就够了。

在举个例子,现在变成“小鱼”改吃 “金币”了。“小鱼”需要穿越过“金币”的碰撞区域,在回到上面我说的Rigidbody2D组件上。此时请把“小鱼”身上的 Is Kinematic 勾选上。并且把Box Collider2D上的 Is Trigger勾选。

Unity2D研究院之精灵Sprite之间的碰撞事件(三) - 雨松MOMO程序研究院 - 4

把如下脚本挂在“小鱼”身上。

OnTriggerEnter2D 表示进入碰撞的事件,对应还有碰撞中、和碰撞结束的事件。如下图所示,“小鱼”已经可以穿过碰撞区域了。

Unity2D研究院之精灵Sprite之间的碰撞事件(三) - 雨松MOMO程序研究院 - 5

例子4: 如果“小鱼”既要响应碰撞也要响应触发该如何?也就是说“小鱼”碰到石头会停止,但是同时碰到金币则会穿越。此时“小鱼”身上的Box Collider2D不要勾选Is Trigger,而是“金币”勾选Is Trigger即可。

总结:

1.精灵之间Game视图显示上没有碰撞表现,但代码要监听碰撞事件,那么 Is Kinematic 勾选,Is Trigger勾选、用transform.postion给坐标赋值即可。

2.精灵之间Game视图显示上要有碰撞表现,并且代码要监听碰撞事件。那么Is Kinematic 不勾选,Is Trigger不要勾选,用Rigidbody2D来给坐标赋值即可。

如果想做插值动画, 新项目的话强烈建议使用DoTween http://dotween.demigiant.com/ 虽然目前还是Alph版本,但是功能已经很强大的,我相信很快就有正式版本了。

最后感谢大家听我唠叨,如果有好的建议或者方法欢迎大家在下面给我留言,互相学习与进步,加油~嘿嘿。

最后编辑:
作者:雨松MOMO
专注移动互联网,Unity3D游戏开发
捐 赠写博客不易,如果您想请我喝一杯星巴克的话?就进来看吧!

Unity2D研究院之精灵Sprite之间的碰撞事件(三)》有 27 条评论

  1. 小轩 说:

    可否有Demo,求demo

  2. kobechen413 说:

    OnTriggerEnter2D 为什么会检测碰撞了好几次,好奇怪

  3. 周震杰 说:

    abc三个球 以及 地面d,abc都有重力影响并 可掉落在 d上 , a和b 相互 不发生物理碰撞 , c和 ab 球 能发生 物理碰撞。
    请问 如何解

  4. Breakout 说:

    请教前辈一个问题,目前在边学边做一个坦克射击小游戏(3d的),目前遇到的问题是发射出的炮弹经常穿过目标,就是说检测不到碰撞,这个问题已经困扰了我很久。。所以想问问前辈U3D在这种射击游戏判断是否击中目标方面有没有什么好的解决方案??

  5. gngnxx 说:

    请问:在3D中的鱼在寻路移动的过程中被其他与挡住了,要怎么弄。我起初是想,选itween寻路,碰撞检测在重新分布路线。 有没有其他好的方法

  6. 星尘小雨 说:

    在unity中,boxcollider2D和rigibody2D之间会出现很小的一条缝隙,这个能解决么

    • 雨松MOMO 说:

      把boxcollider2D 的区域做小一点吧。。

      • 星尘小雨 说:

        可能我表达得不清楚,首先是角色是添加了rigibody2d和boxcollider2d2个组件,然后场景上的墙壁和地面是添加了静态的boxcollider2d的组件,当启动游戏后,角色和地面之间就会出现一条小的缝隙,我google了一下说是当碰撞检测出刚体和碰撞盒重叠了的情况下,会自动把2者分开,之间形成一个小的缝隙,但我现在做着一个2D的格子类型的游戏,如果用刚体来实现效果的话,墙和角色的单位是1的情况下,那么角色就穿不过由2个墙构成的单位1的路线了,因为角色的坐标因为那个缝隙抬高了

        • 雨松MOMO 说:

          我知道你说的这个问题, 我以前也遇到了,但是没找到合适的解决方法, 后来做了一个小工具自动生成boxcollider区域。 比显示区域稍微小一些就OK了。

  7. 杨永松 说:

    2d单向碰撞有什么好办法吗,像3d的平面一样那种

  8. jlb 说:

    请教下鱼松,两个问题,一个是 刚体的角色从 高处下落到地面后, x左边会稍微发生点变化,貌似收到了摩擦一样,可是我刚体的摩擦力已经都设置为0了,但好像还是收到了摩擦力一样。后来把碰撞体都勾选isTrigger的方法,通过检测来控制物体的刚体,x位置倒不会发生变化了,但是如果刚体的下来速度很快,trigger那个检测会有延迟 也就是说,物体下落高度越搞 会更加陷入地面,请问这种怎么解决。 我还想用射线去尝试下怎么 解决这个两难的问题

  9. 请教大神,在对象上加了2d的 碰撞器 和 2d刚体之后,该怎么使用Drag Object这个组件对这个对象进行拖拽,就是要怎么实现2d碰撞器的拖拽?谢谢了,求指点。

  10. 宇骐 说:

    请教大神,在对象上加了2d的 碰撞器 和 2d刚体之后,该怎么使用Drag Object这个组件对这个对象进行拖拽,就是要怎么实现2d碰撞器的拖拽?谢谢了,求指点。

  11. 小糊涂神 说:

    请问NGUI的两个sprite之间能做碰撞检测么?

  12. 源代码 说:

    我觉得把坐标锁定不是很好嘛。简单粗暴,省事省力省心。。。。。。 Unity2D研究院之精灵Sprite之间的碰撞事件(三) - 雨松MOMO程序研究院 - 1

  13. MATI MAKU 说:

    想请教MOMO个问题,表面着色器里如果想对UV进行矩阵变换应该怎么写啊 求教

留下一个回复

你的email不会被公开。