❶ 3D游戲是怎麼檢測碰撞的
首先假設你對與碰撞檢測相關的幾何和數學知識已經有了基本的了解。在文章的最後,我將提供一些這方面的參考資料,以免你對它們感覺有點生疏。另外我還假設你已經讀過 Jeff Lander 的圖形專欄里關於碰撞檢測文章(「Crashing into the New Year,」 ; 「When Two Hearts Collide,」;和 「Collision Response: Bouncy, Trouncy, Fun,」)。我將首先進行一個大概的描述,然後快速地切入到核心內容里,通過這兩步從上至下地深入到碰撞檢測中。我將討論兩種類型的圖形引擎中的碰撞檢測:基於 portal 的和基於 BSP 的。每種引擎中多邊形的組織各不相同,因此在 world-object 型的碰撞檢測上存在很大的差別。而object-object 型的碰撞檢測絕大多數地方在上述兩種引擎里的是一樣的,主要看你是如何實現的了。當我們接觸到多邊形的碰撞檢測時,我們還會實驗如何將其擴展到我們學過的凸型物體上。
為了創建一個理想的碰撞檢測程序,我們不得不在開發一個游戲的的圖形管道的同時就開始計劃並創建它的框架。在項目的最後加入碰撞檢測是相當困難的。想在開發周期的末尾創建快速的碰撞檢測將很有可能會使整個游戲被毀掉,因為我們不可能使它能高效地運行。在好的游戲引擎中,碰撞檢測應該是精確、有效並且十分快速的。這些要求意味著碰撞檢測將要與場景的多邊形管理管道緊緊地聯系起來。這也意味著窮舉法將無法工作??今天的3D游戲中每幀處理的數據量很可能導致打格,當你還在檢測一個物體的各多邊形是否與場景中的其它多邊形碰撞時,時間已經過去了。
讓我們從基本的游戲引擎循環開始吧(列表1)。快速瀏覽這些代碼來得到碰撞檢測的相關策略。我們先假設碰撞沒有發生,然後更新物體的位置,如果發現發生了碰撞,我們將把物體移回原來的位置不允許它穿越邊界(或將物體銷毀或執行一些預防措施)。然而,這個假設太過簡單因為我們無法得知物體原來的位置是否仍然有效。你必須為這種情況設計一個方案(否則你可能會體驗到墜機或被子彈擊中的感覺??就是前面舉的例子)。如果你是一個熱心的玩家,你可能已經注意到了在一些游戲當中,當你挨著牆壁並試圖穿過去的時候,攝像機就開始震動。你正經歷的就是將主角移回原位的情況。震動是因為取了較大的時間片引起的。
Listing 1. Extremely Simplified Game Loop
while(1){
process_input();
update_objects();
render_world();
}
update_objects(){
for (each_object)
save_old_position();
calc new_object_position
{based on velocity accel. etc.}
if (collide_with_other_objects())
new_object_position = old_position();
{or if destroyed object remove it etc.}
Figure 1. Time gradient and collision tests.
但是我們的方法有缺陷,我們忘了在等式中加入時間。圖1告訴我們時間太重要了不能忘了它。即便物體在 t1 或 t2 時刻沒有發生碰撞,它仍有可能在 t 時刻穿過邊界(t1
我們可以把時間看成是第四維並將所有運算在4維空間中進行。然而這可能會讓運算變得十分復雜,所以我們會避開這些。我們還可以創建一個以 t1、t2時刻的物體為起始點的實心體,然後用它來與牆進行測試(見圖2)Figure 2. Solid created from the space that an object spans over a given time frame.
一個簡單的方法就是創建一個凸殼來罩住兩個不同時刻的物體。這種方法效率低下可能會明顯地降低你的游戲速度。以其創建一個凸殼,還不如創建一個圍繞實心體的包圍盒。我們學習其它的技術後再回來討論這個問題。
有另一種比較容易執行但精度較低的方法,就是把給定的時間段分為兩分,然後測試時間中點的相交關系。我們還可以遞歸地依次測定各段的時間中點。這個方法比先前的方法要快得多,但不能保證能捕捉到所有的碰撞情況。另一個暗藏著的問題是collide_with_other_objects()方法的實現??即判斷一個物體是否與場景中的其它物體相交。如果場景中有很多的物體,這個方法可能消耗很大。如果要判斷各物體與場景中其它物體是否相交,我們將不得不進行大概N選2次比較。因此比較次數會是N的平方次?(或表示成O(N2))。但我們可以用幾種方法來避免進行O(N2)對的比較。舉個例子,我們可以把場景中的物體分成靜態的(被撞物)和動態的(碰撞物??即使它的速度為0也行)。就好象房間中的牆壁是被撞物,而一個扔向牆壁的小球是碰撞物。我們可以創建兩棵獨立的樹(每一棵對應一類物體),然後測試那些物體可能會碰撞的樹。我們甚至可以對環境進行約定讓一些碰撞物之間不發生碰撞??比如我們不需要在兩顆子彈之間進行判斷。現在在繼續之前,(經過改進之後)我們可以說處理過程變得更加清晰了。(另一個減少場景中成對的比較的方法就是建立八叉樹。這已經超出了這篇文章的范圍,你可以在Spatial Data Structures: Quadtree, Octrees and Other Hierarchical Methods文章中的For Further Info一節里讀到更多關於八叉的信息)。現在讓我們來看一下基於 Portal 引擎,了解為什麼在這類引擎中一提到碰撞檢測就會那麼痛苦。
Portal引擎和Object-Object型碰撞
基於 Portal 的引擎把場景或世界分割成較小的凸方形區域。凸方形區域很適合圖形管道因為它們能避免重繪現象。不幸的是,對碰撞檢測來說,凸方形區域會給我們帶來一些困難。在我最近的一些測試中,一個引擎中平均大約有400到500個凸方形區域。當然,這個數字會隨著不同的引擎而有所變化,因為不同的引擎使用不同的多邊形技術。而且多邊形的數目也會因場景的大小而有所不同。
判斷一個物體的多邊形是否穿過了場景中的多邊形產生的運算量可能會很大。一個最簡單的碰撞檢測法就是用球形來近似地表示物體或物體的一部分,然後再判斷這些包圍球是否相交。這樣我們僅僅需要測試兩個球體中心的距離是否小於它們的半徑合(這表示發生了碰撞)。如果我們是用中心點距離的平方和半徑合的平方進行比較,那更好,這樣我們可以在計算距離時除去拙劣的開方運算。但是,簡單的運算也導致了精確度的降低(見圖3)。
Figure 3. In a sphere-sphere intersection, the routine may report that collision has occurred when it really hasn』t.
但我們僅僅是將這個不太精確的方法做為我們的第一步。我們用一個大的球體代表整個對象,然後檢測它是否和其它的球體相交。如果檢測到發生了碰撞,那麼我們就要進一步提高精度,我們可以將大的球體分割成一系列小的球體,並檢查與各小球體是否發生碰撞。我們不斷地分割檢查直到得到滿意的近似值為止。分層並分割的基本思想就是我們要盡可能達到適合需要的理想的情況。
Figure 4. Sphere subdivision.
用球體去近似地代表物體運算量很小,但在游戲中的大多數物體是方的,我們應該用方盒來代表物體。開發者一直用包圍盒和這種遞歸的快速方法來加速光線追蹤演算法。?謔導手校�廡┧惴ㄒ丫�園瞬婧虯ABB(axis-aligned bounding boxes)的方式出現了。圖5展示了一個AABB和它裡面的物體。Figure 5. An object and its AABB.
坐標軸平行(「Axis-aligned」)不僅指盒體與世界坐標軸平行,同時也指盒體的每個面都和一條坐標軸垂直。這樣一個基本信息就能減少轉換盒體時操作的次數。AABBs 在當今的許多游戲中都得到了應用,開發者經常用它們作為模型的包圍盒。再次指出,提高精度的同時也會降低速度。因為 AABBs 總是與坐標思平行,我們不能在旋轉物體的時候簡單地旋轉 AABBs --- 它們應該在每一幀都重新計算過。如果我們知道每個對象的內容,這個計算就不算困難並不會降低游戲的速度。 然而,我們還面臨著精度的問題。假如我們有一個3D的細長剛性直棒,並且要在每一幀動畫中都重建它的AABB。我們可以看到每一幀中的包圍盒的都不一樣而且精度也會隨之改變。
❷ 碰撞檢測的原理是什麼virtools中提供了幾種碰撞檢測的方法有何不同
四班童鞋,按檢測方式又可以分為離散點的碰撞檢測和連續碰撞檢測(CCD continuous collision detection)。離散點的碰撞檢測是指定某一時刻T的兩個靜態碰撞體,看它們之間是否交迭,如果沒有交迭則返回它們最近點的距離,如果交迭則返回交迭深度,交迭方向等。連續碰撞檢測則是分別指定在T1、T2兩個時刻兩個碰撞體的位置,看它們在由T1運動到T2時刻的過程中是否發生碰撞,如果碰撞則返回第一碰撞點的位置和法線。連續碰撞檢測是最為自然的碰撞檢測,可以大大方便碰撞響應邏輯的編寫,可以很容易避免物體發生交迭或者穿越。離散點的碰撞檢測則沒有那麼友好,當檢測到碰撞時兩個物體已經發生了交迭,如果其中有三角形網格對象那麼已經有許多三角形發生了交迭,如何將兩個交迭的對象分開並按合理的方式運動是一個挑戰。雖然連續碰撞檢測是最自然的方式,但它的實現非常復雜,運算開銷也很大,所以目前大部分成熟的物理引擎和碰撞檢測引擎還是採用了基於離散點的碰撞檢測,為了避免物體交迭過深或者彼此穿越,大多都要採用比較小的模擬步長。
❸ unity 怎麼判斷碰撞的物體
發生碰撞條件如下:
兩個對象都有Collider組件且至少一個有Rigidbody組件其中至少一個物體(必須運動的)必須帶有碰撞器(collider)+剛體(Rigidbody),另一個物體(可以靜止也可以運動)也必須至少帶collider也有說一方有CharacterController,另一方有Collider。
詳解如下:
(1)添加了CharacterController組件後,人物將不受力影響,這時即使加上Rigidbody組件,並啟用Use Gravity。人物也不會受重力影響,在腳本中通過rigidbody對人物施加力也是無效的。
也就是說CharacterController屏蔽了Rigidbody的所有屬性和方法。要控制CharacterController移動,可以通過在腳本中調用Move方法使其移動。
(2)雖然CharacterController不受力,但是有個例外是,它受碰撞的影響。
一般的碰撞發生條件是:碰撞的兩個物體必須都有Collider,並且其中一個有Rigidbody。
但是如果一方有CharacterController,則不需要。
這時碰撞發生的條件為:一方有CharacterController,另一方有Collider。CharacterController本身就繼承自Collider。
(3)碰撞發生時,CharacterController不會推動其它物體移動,也就是說CharacterController不會對它所碰撞的物體施加物理作用。除非我們在腳本中添加了OnControllerColliderHit()函數,在該函數中使用被碰撞物體的rigidbody對被碰撞物體施加力。
(3)碰撞體的檢測方法擴展閱讀:
如何學習unity:
第一步首先了解unity3d的菜單,視圖界面。這些是最基本的基礎,可以像學word操作一樣,大致能明白有幾個菜單,幾個基本的視圖,各自起什麼作用的就可以了。當然還要了解人物基本的比例和結構。
第二步理解場景裡面的坐標系統,輸入系統,簡單的向量概念。Unity3D的坐標系統及向量概念如果不理解清楚,不理解世界坐標,局部坐標的關系,即使一個簡單的移動,縮放,旋轉的幾行代碼,也會困惑你半天。
第三步學習創建基本的場景的一些基本概念:游戲對象,組件,腳本。在界面上分別體現在層次視圖,項目視圖及屬性視圖,要理清楚彼此之間的關系
第四步學習資源導入方面的一些基本元素:網格,材質,貼圖,動畫等。
第五步學習腳本的生命周期,Start,UpDate,ONGUI這些基本的方法。了解,預制,時間,數學等常用的類及相關方法。理解游戲對象,組件,腳本彼此之間的關系。
第六步進一步學習攝像機,燈光,地形,渲染,粒子系統,物理系統等等,這些每一個深入進去都是一個很復雜的主題。
第七步一些更高級的概念:向量的加減法點乘叉乘,光照法線貼圖,內存管理,圖形優化等等。Unity3D入門容易,真的要精通,那是相當難的。
❹ Unity 3D中碰撞檢測中有多少個方法(送分的)
OnTriggerEnter
OnTriggerEnter is called when the Collider other enters the trigger.
OnTriggerExit
OnTriggerExit is called when the Collider other has stopped touching the trigger.
OnTriggerStay
OnTriggerStay is called almost all the frames for every Collider other that is touching the trigger.
OnCollisionEnter
OnCollisionEnter is called when this collider/rigidbody has begun touching another rigidbody/collider.
OnCollisionExit
OnCollisionExit is called when this collider/rigidbody has stopped touching another rigidbody/collider.
OnCollisionStay
OnCollisionStay is called once per frame for every collider/rigidbody that is touching rigidbody/collider.
基本就是這些,
1,開始接觸到其他碰撞體
2,持續接觸其他碰撞體
3,停止接觸其他碰撞體
❺ 怎麼檢測物體和邊界的碰撞
也帶來了一個新的問題:攝像頭移動的時候,毫無阻攔,這就是所謂的「穿牆模式」。有沒有什麼辦法解決這個問題呢?有,就是在移動攝像頭前先進行「碰撞檢測」,確定攝像頭的新位置區間中沒有其他的三維模型。本文將介紹如何在WPF中進行三維碰撞檢測。利用Rect3D.IntersectsWith 方法在進入下一節前,先看看最簡單的碰撞檢測方式:利用Rect3D.IntersectsWith 方法。Model3D有一個Bounds屬性,用來表示該Model3D的邊界:該屬性是Rect3D類型的,我們可以使用IntersectsWith 來確定相機位置所在的矩形是否與此Rect3D相交。如果是,則說明相機移動到Rect3D內部,沖突發生;如果否,則表示相機離Model3D還有一段距離,可以放心地移動。沒有發生碰撞發生碰撞的情況使用Rect3D.IntersectsWith 方法,對於規規矩矩的正方體來說,效果很好。但是如果使用Rect3D.IntersectsWith 方法檢測攝像機是否和不規則物品的外接多邊形發生碰撞,精確性會降低很多。就拿上圖來說,紅色方塊所在的攝像機實際上和房子還有很遠一段距離,但卻在房子所在區域里,這個時候,Rect3D.IntersectsWith 檢測的結果是「碰撞發生了」。因此,需要用稍微復雜一點的方法,VisualTreeHelper.HitTest方法,對三維物品進行命中測試,以處理不規則物品的碰撞檢測問題。利用VisualTreeHelper.HitTest 方法VisualTreeHelper.HitTest是由三個函數重載而成的,在三維世界裡,使用:public static void HitTest( Visual3D reference, HitTestFilterCallback filterCallback, HitTestResultCallback resultCallback, HitTestParameters3D hitTestParameters ) 方法來進行命中測試。reference:要進行命中測試的 Visual3D。 也就是場景中的不規則的三維物品。filterCallback:表示命中測試篩選回調值的方法,有時候,並非所有的三維物品都是不可穿越的,例如泳池中的水,在沒有結冰的前提下是阻止不了Camera移動的,因此,可以filterCallback設置這些物體。resultCallback:表示命中測試結果回調值的方法。hitTestParameters:要進行命中測試的三維參數值。對於最後一個參數,hitTestParameters,使用的是HitTestParameters3D的一個子類:RayHitTestParameters(也是目前HitTestParameters3D的唯一子類)。該類表示一個射線。看到這里,你大體會意思到如何使用VisualTreeHelper.HitTest來進行碰撞檢測了吧。沒錯!
❻ 如何檢測一個物體是否與別的物體碰撞
使用Raycaster進行碰撞檢測
用Raycaster來檢測碰撞的原理很簡單,我們需要以物體的中心為起點,向各個頂點(vertices)發出射線,然後檢查射線是否與其它的物體相交。如果出現了相交的情況,檢查最近的一個交點與射線起點間的距離,如果這個距離比射線起點至物體頂點間的距離要小,則說明發生了碰撞。
這個方法有一個 缺點 ,當物體的中心在另一個物體內部時,是不能夠檢測到碰撞的。而且當兩個物體能夠互相穿過,且有較大部分重合時,檢測效果也不理想。
還有需要 注意 的一點是:在Three.js中創建物體時,它的頂點(veritces)數目是與它的分段數目相關的,分段越多,頂點數目越多。為了檢測過程中的准確度考慮,需要適當增加物體的分段。
❼ unity3d 怎麼檢測碰撞比如主角碰撞到物體之後銷毀被撞到的物體
首先創建一個「立方體」與一個「粒子系統」,立方體在粒子可以碰撞到的范圍內。
選擇粒子系統,在屬性中「Tag」中選擇「Add Tag」添加一個「aa」。
勾選「shape」,其中的shape設置為「Box」。
勾選「Collision」,選擇「Word」,勾選「Send Collision Message」。
創建腳本,添加「OnParticleCollision」方法,通過aa這個tag判斷粒子碰撞。
把腳本放在立方體上。
現在ctrl+p運行游戲,我們發現console中會顯示我們設置的碰撞提示,這就表示粒子系統粒子碰撞檢測成功了。
❽ c++ 游戲碰撞檢測怎麼做
在游戲開發中,經常需要進行碰撞檢測演算法的實現,例如判斷前面是否有障礙以及判斷子彈是否擊中飛機,都是檢測兩個物體是否發生碰撞,然後根據檢測的結果通過碰撞檢測演算法做出不同的處理。
進行碰撞檢測演算法的物體可能有些的形狀和復雜,這些需要進行組合碰撞檢測,就是將復雜的物體處理成一個一個的基本形狀的組合,然後分別進行不同的檢測。
下面簡單介紹一下兩種最基本的形狀進行碰撞的時候進行的處理。
1、矩形和矩形進行碰撞檢測演算法
一般規則的物體碰撞都可以處理成矩形碰撞,實現的原理就是檢測兩個矩形是否重疊。我們假設矩形1的參數是:左上角的坐標是(x1,y1),寬度是w1,高度是h1;矩形2的參數是:左上角的坐標是(x2,y2),寬度是w2,高度是h2。
在檢測時,數學上可以處理成比較中心點的坐標在x和y方向上的距離和寬度的關系。即兩個矩形中心點在x方向的距離的絕對值小於等於矩形寬度和的二分之一,同時y方向的距離的絕對值小於等於矩形高度和的二分之一。下面是數學表達式:
x方向:| (x1 + w1 / 2) – (x2 + w2/2) | < |(w1 + w2) / 2|
y方向:| (y1 + h1 / 2) – (y2 + h2/2) | < |(h1 + h2) / 2|
在Java ME程序中,只需要將上面的條件轉換成代碼就可以實現了。
但是矩形碰撞只是一種比較粗糙的碰撞檢測演算法,因為很多實際的物體可能不是一個規則的矩形。
下面介紹一下圓形碰撞。
2、圓形和圓形的碰撞檢測演算法
圓形和圓形的碰撞應該說是一種最簡單的碰撞,因為在數學上對於兩個圓形是否發生重疊,有計算兩個圓心之間的距離的公式。那麼條件就變為:計算兩個圓心之間的距離是否小於兩個圓的半徑和。
假設圓形1的左上角坐標是(x1,y1),半徑是r1,圓形2的左上角的坐標是(x2,y2),半徑是r2。
因為MIDP1.0中沒有浮點數,而且浮點數的運算比較慢,所以我們將條件做一個簡單的變換:對於條件的兩邊都進行平方,這樣就去掉了開方的運算步驟。
下面是數學表達式:
(x1 – x2)2 + (y1 – y2)2 < (r1 + r2)2
在Java ME程序中,只需要將上面的條件轉換成代碼就可以了。
上面介紹的只是最基本的碰撞檢測演算法的實現,而實際的編程過程中遇到的碰撞檢測問題要比這些復雜很多,還需要其他形式的檢測,還需要進行更加深入的學習。
❾ 使用射線Raycast判斷某個方向是否有碰撞體
public class NewBehaviourScript : MonoBehaviour {
void Start () {
if (Physics2D.Raycast(this.transform.position, Vector2.down, 10.0f,
1 << LayerMask.NameToLayer("Collider"))) {
string colliderName = Physics2D.Raycast(this.transform.position, Vector2.down, 10.0f,
1 << LayerMask.NameToLayer("Collider")).collider.gameObject.name;
Debug.Log("Collider " + colliderName + " is under the CubeUp");
}
else {
Debug.Log("No collider is under the CubeUp");
}
}
void Update () {
}
}
可以看到這里需要把下方物體CubuDown的Layer設置為Collider(上方物體CubeUp不需要設置):
運行後:
即可以檢測到下方有碰撞體。
❿ 一個物體上有多個碰撞體,碰撞體如何檢測
.版本 2 .支持庫 iext2 .程序集 窗口程序集1 .程序集變數 汽車A, 整數型 .程序集變數 汽車B, 整數型 .程序集變數 變數2, 整數型 【需要用到的變數】 .子程序 __啟動窗口_創建完畢 汽車A = 動畫框1.創建物體 (, 1, 1, 真, ) 汽車B = 動畫框1.創。