Unity3D学习笔记(六) 关于碰撞
(2012-07-11 23:23:40)
1.碰撞主要有三个函数,void OnCollisionStay,void OnCollisionEnter和OnCollisionExit,三个函数都是回调函数,都有(collisionInfo : Collision)参数。
2.一般而言,子弹等物体要进行与Player的消除碰撞处理:
Physics.IgnoreCollision(clone.collider,this.collider);
3.脚本附在子弹上时,collisionInfo对象由Collision类生成,则collisionInfo包含被碰撞对象信息。另外:
①collisionInfo.collider就是子弹撞击的物体的碰撞器,获取被撞击物体的名字则通过变量collisionInfo.collider.name(这不是代表碰撞器类型名,而且组件附加物体的物体名称),经常用这个来判断对不同碰撞对象的处理(子弹与物理世界则消失,子弹与敌人子弹则受力运动,子弹与敌人则消失扣血)。
②collisionInfo.transform可以获得被撞击物体的变换属性。
③collisionInfo.contacts是ContactPoint[]数组。一般只使用collisionInfo.contacts[0],代表碰撞接触点。动态生成爆炸效果时常用,0号元素位置作为出生点位置,用以下结果作为出生旋转值(使爆炸沿碰撞点表面法线方向,更为真实):
4.对于某些枪械,比如霰弹枪发射的子弹,有时需要做物体受子弹作用力被击飞的效果(对于敌人除了击飞有时还会伴有摔倒效果),这时首先可以用射线函数判断是否击中物体,并获取子弹击中点:
if (Physics.Raycast (originPosition, direction, hitInfo, distance)){.....}
//这一句是放在player身上的(在每次发射子弹时),个人觉得其实在某些场景物体或者敌人身上附加脚本利用collisionInfo去获取子弹碰撞情况下的撞击点,然后针对性地做各种反应会好一点。不过可能受力方向比较难判断,可以考虑在子弹脚本Start()中保存出生点,再依据碰撞点得到子弹运动方向,注意子弹有无重力都只考虑撞击点y坐标。
获取到击中点后即可对该点施加子弹冲击力:(先判断物体是否属于刚体)
if (hit.rigidbody) hit.rigidbody.AddForceAtPosition(force * direction, hitInfo.point);
5.爆炸的局部空间动力效果的实现。首先获取在爆炸点的某个球体半径范围内的所有碰撞体:
Collider[] colliders = Physics.OverlapSphere( transform.position,explosionRadius );
此函数除了包含位置,半径外还有默认参数遮罩层级(进行碰撞器筛选)。
接着对所有碰撞体施加力,unity内置了添加爆炸力函数:
foreach (Collider hit in colliders) { if (!hit) continue; //防止碰撞体不存在?貌似多余?
//防止碰撞体hit不存在rigidbody程序出错,只对存在刚体属性的碰撞体添加爆炸作用力。通过这个区别也可以设置一些不受爆炸影响的物体(比如terrain)。
if (hit.rigidbody) hit.rigidbody.AddExplosionForce(explosionPower, explosionPos,explosionRadius);
//此函数还含有第四个参数upwardsModifier(正数n代表虚拟爆炸点在物体中心的下方n米处),可适当设置以增加一个物体下方的虚拟爆炸力,炸飞效果更酷。参数要适当大,否则虚拟爆炸点在物体内部效果有点奇怪。
附注:AddExplosionForce也可以用于制作球形范围内的引力,只要设置了负的作用力。
6.在5中的情况,如果除了有爆炸作用力还需要计算按距离衰减的爆炸杀伤力,首先需要计算每个物体离爆炸点最近的表面点坐标:
Vector3 closestPoint = hit.rigidbody.ClosestPointOnBounds(explosionPosition);
接着要计算表面点坐标与爆炸中心距离:float distance = Vector3.Distance(closestPoint, explosionPos);
最后依照爆炸威力随距离衰减的原则计算物体所受伤害占爆炸总伤害的百分比:
float damage = (1.0F - Mathf.Clamp01(distance / explosionRadius))*explosionDamage;