如果你在Unity里面使用了Rigidbody, 並且勾選了Is Kinematic 想自己通過Transfrom來控制角色的位置的話。那么你一定會碰到如果角色跑動快了,會插入到其他運動的角色或者靜止的單位中,比如牆壁,建築等等。
1:網上的解決方案: (老的解決方案)
網上到是有解決方案,不過都太復雜,都需要自己去預判下一步的步長,這個就是以前的沒有引擎的老方法,原理就是如果下一步會被碰到就把下一步的位置直接設置到碰撞的邊緣,而不是走滿那一步。既然說到這里我們就要說一下Unity帶來的全新的解決方案,使用球狀射線的原理。Unity摘錄如下:
2:我的解決方案(球體射線碰撞)
Physics.SphereCast 球體投射
static function SphereCast (origin : Vector3, radius : float, direction : Vector3, out hitInfo : RaycastHit, distance : float = Mathf.Infinity, layerMask : int = kDefaultRaycastLayers) : boolean
Parameters參數
-
originThe center of the sphere at the start of the sweep.
在掃描起點的球體中心點。 -
radiusThe radius of the sphere.
球體的半徑。 -
directionThe direction into which to sweep the sphere.
球體掃描的方向 -
hitInfoIf true is returned, hitInfo will contain more information about where the collider was hit (See Also: RaycastHit).
如果返回true,hitInfo將包含碰到器碰撞的更多信息。 -
distanceThe length of the sweep
掃描的長度 -
layerMaskA Layer mask that is used to selectively ignore colliders when casting a capsule.
根據Layer mask層的不同來忽略碰撞體。
Returns
boolean - True when the capsule sweep intersects any collider, otherwise false.
當膠囊物體投射時與碰撞體相交時,返回真,否則返回假。
原理: 把你的角色當成一個球型包圍的物體,以他為中心,像一個球體發射射線,如果射線檢查到碰撞體那么就認為碰撞了,然后就該處理你自己的邏輯,比如讓角色停止,反彈,等等。以下是我在游戲中用到的
//0.7米處有碰撞急停 void Update () { RaycastHit hit; Vector3 p1 = transform.position; Vector3 p2 = p1 + Vector3.forward * 0.5f; if(Physics.CapsuleCast(p1, p2, 0.0f, transform.forward, out hit, 0.2f)) {
//停止該角色 CActionControl.Instance().OnStopMove(uqid_); } }
3:說一說當初實現的方案以及為什么不行
最初想法是MonoBehaviour.OnCollisionEnter 使用這個接口來檢測碰撞,但是這個接口只會檢測出你碰撞的瞬間。也就是說你碰撞提接觸的瞬間,但是並不會保證你沒有在碰撞了。也就是說MonoBehaviour.OnCollisionStay狀態可能一直存在,那么你下次就無法檢測是否碰撞了,甚至到后來可能會兩個角色都合體了。
也並不是說這個方案實現不了,但是會非常的復雜,比如你想反彈,當兩個角色發生了MonoBehaviour.OnCollisionEnter的時候就按照碰撞方向的反方向進行反彈操作,具體的反彈代碼只能自己去實現了(由於你是自己控制的Transfrom),而且如果對象多了的話可能會導致,對象像盪秋千一樣彈過去了又彈過來。所以這里避免了這種情況,表示這種實現方案在游戲中很難做到!
