内置的碰撞检测
Unity中开启碰撞检测至少需要一方拥有RigidBody
,通过OnCollisionEnter
方法检测到碰撞
内置碰撞检测的不足
如果我们需要对物理检测进行更精准的定位,可以修改它的检测模式和线性检测方法。将将body的检测模式更改为连续检测模式或者动态连续检测模式。将线性改为线性模式。
1 2 3
| Rigidbody rigidbody; rigidbody.collisionDetectionMode = CollisionDetectionMode.Continuous; rigidbody.interpolation = RigidbodyInterpolation.Interpolate;
|
经过以上调整,我们可以发现并没有得到很好的效果,子弹仍然会在穿墙之后爆炸或者不爆炸。
使用射线检测辅助
经过研究发现仍然问题仍然出现在子弹的速度过快。因为unity的物理是在fix update中进行。
如果当前的update和下一个update的间隔过大。我们仍然不能检测到中间的物体。
但是,我们使用射线在curTime
->nextTime
和preTime
->curTime
都进行射线检测,这样确保两个fixupdate
之间检测到了物体。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51
| private void FixedUpdate() { if (startTime < 0) startTime = Time.time; var curTime = Time.time - startTime; var preTime = curTime - Time.fixedDeltaTime; var nextTime = curTime + Time.fixedDeltaTime; var curPoint = GetBulletPos(curTime); RaycastHit tempHit; if (preTime > 0) { var prePoint = GetBulletPos(preTime); if (Physics.Linecast(prePoint, curPoint, out tempHit)) { OnHit(tempHit); } } var nextPoint = GetBulletPos(nextTime); if (Physics.Linecast(curPoint, nextPoint, out tempHit)) { OnHit(tempHit); } }
private void OnHit(RaycastHit hit) { Debug.Log(hit.collider.name); BaseTank hitTank = hit.collider.gameObject.GetComponent<BaseTank>(); if (hitTank == tank) { return; } if (hitTank != null) { SendMsgHit(tank, hitTank); } ... }
|
可以得到非常好的效果了,当时觉得hit.point
的位置任然不是很完美,稍微跳转下即可
1 2 3 4 5 6 7 8 9
|
GameObject explode = ResMgr.Instance.AutoLoad<GameObject>("BigExplosion"); Vector3 tempHitPoint = new Vector3(hit.point.x, hit.point.y, hit.point.z - 0.5f);
explode.transform.SetPositionAndRotation(tempHitPoint, transform.rotation); Destroy(explode, 1); Destroy(gameObject);
|