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;
文章列表