Unity-碰撞

邱繼祥
Unity
Published in
5 min readJul 23, 2019

原文: https://blog.csdn.net/andyhan_1001/article/details/76286018

本篇目的:解決CharacterController碰撞帶有isTrigger的collider穿透問題

Rigidbody

用在本身不會活動的“物體”上,他們是靠物理系統運動。

不要使用Translate()來讓物體運動,要用各種“力”, 例如:Rigidbody的AddForce()方法,通過“力”來讓它移動。

Rigidbody可以和NavMeshObstacle合用,因為後者也是用在“物體”上的,但是一般不要和NavMeshAgent合用,因為這兩個都會控制物體的運動,這樣會有race condition。如果非要合用,請勾選Is Kinematic,由此看來如果Rigidbody的Is Kinematic屬性被勾選了,那麼Rigidbody就可以和任何其他的Component合用了,比如:NavMeshAgent,CharacterController。

Rigidbody會對“力”產生響應,如果一個物體加上了Rigidbody,首先會直接對“重力”產生響應,如果再加上Collider,就會對其他“力”產生響應了。同時如果使用Translate()移動Rigidbody,那麼它會對其他的Rigidbody在碰撞的時候自動施加一個“力”。

Collider

Collider是碰撞檢測的基礎。

Collider分為static collider和dynamic collider

static collider:

指的是相互碰撞的兩個物體沒有附加剛體而只附加了Collider的遊戲對象。這類對像在碰撞時會保持靜止,發生碰撞時不會觸發任何的方法函數

沒有Rigidbody的collider,最好是靜止的物體,不要通過改變他的transform的position來使它運動,這樣不僅會給物理引擎造成很多性能損失,而且會產生一些無法預測的行為。

#註 : 非要通過Translate( )移動,且不希望被物理引擎控制,則需要加上一個勾選了Is Kinematic的Rigidbody(Is Kinematic是讓Rigidbody不受物理引擎的控制)

dynamic collider:

有Rigidbody的collider

在靜態碰撞器的基礎上,處於運動狀態的物體必須要附加剛體組件和帶有碰撞檢測函數的腳本,被撞的物體可以沒有剛體組件或碰撞檢測腳本。 當兩個物體發生碰撞時,帶有剛體組件的物體會發生物理特性,如被撞飛,或有摩擦力的影響下移動一段距離。

CharacterController

不對任何“力”產生作用,同時也不對物體施加“力”,即使物體是Rigidbody。

(不要再加Collider,CharacterController有自帶的Capsule Collider。並且使用Move()方法移動物體)

*重點

Collider中Is Trigger的優先級高於Rigidbody(不管這個被標記為Is Trigger的Collider和Rigidbody是不是在同一個GameObject上)

因為Rigidbody是根據Collider來進行物理模擬,Collider是Rigidbody的基礎

為何CharacterController碰撞帶有isTrigger的collider會穿透?

Collider中Is Trigger的優先級也高於CharacterController,不過Collider和CharacterController一般不放在一起,所以這裡指的是對方的物體上Collider的Is Trigger。

由於Trigger只是通過OnTriggerEnter()、OnTriggerStay()、OnTriggerOut()來響應碰撞行為

如果被碰撞的物體Collider的Is Trigger方法勾選了,那麼由於Is Trigger只是將Collider當成了一個“觸發器”,不會響應任何實質碰撞(所謂的實質碰撞,就是能被觀察到的碰撞,比如碰撞之後產生運動碰撞之後阻止物體穿過等等)。所以就算Rigidbody在,也發揮不了作用(OnCollisionEnter()、OnCollisionStay()、OnCollisionOut()不會調用,同時也不會產生物理運動,也不會阻止物體穿過,反正任何可見的碰撞效果都沒有)。

所以CharacterController會穿過被碰撞的物體,並且OnControllerColliderHit()這個回調不會起作用,取而代之的是雙方的OnTrigger*()函數會被調用。

如何解決?

CharacterController 碰撞物體,如果被碰撞的物體有Collider,並且Is Trigger沒有勾選,那麼無論這個物體是不是Rigidbody,CharacterController都會被這個物體“擋”下來,並且只會觸發他自己的OnControllerColliderHit( )這個回調函數(也就是說,如果被碰撞的物體或者它自己有OnTrigger*(),OnCollision*()這種函數,都不會被觸發)。

所以如果我們想要實現一個CharacterController推箱子的遊戲,那麼首先這個箱子必須是Rigidbody,並且Collider不是Is Trigger,而這個“推力”需要在CharacterController的OnControllerColliderHit()這個函數中“發出”了。

判斷碰撞物

void OnControllerColliderHit(ControllerColliderHit hit)
{
if (hit.gameObject.tag==””){要做的事}}

鏡頭不穿牆教學 https://www.youtube.com/watch?v=CZ9SzK5jeWo&t=208s

--

--