Unity 四叉樹QuadTree應用之碰撞檢測

2021-10-06 23:38:43 字數 4369 閱讀 9188

目錄

1.簡介

2.樹的結構

3.構造原則

4.重要介面

5.示例 ​

6.壓測

7.更新

最近在研究四叉樹的二維空間碰撞檢測,隨筆記錄一下

四叉樹顧名思義,就是每科樹都包含4個分支,每個分支可以看做乙個區域象限,用來存放一些資料的空間索引

這裡只討論四叉樹在二維空間的碰撞檢測,unity的實現方式

// 區域象限定義

public enum quadranttype

public enum quadrantbittype

public inte***ce irect

/// /// 矩形的中心座標y

///

float y

/// /// 矩形的寬

///

float width

/// /// 矩形的高

///

float height

}public inte***ce imark

}public class qtreecomparer: icomparer> where t : irect

}// 四叉樹結構

public class qtree: irect where t : irect

public float y

public float width

public float height

public int depth; // 樹的深度

public int childcount; // 物件數量

public bool isleaf; // 是否葉子節點

public listchildlist; // 物件引用

public qtree childnodes; // 子節點陣列(4個)

public qtree()

public qtree(int depth)

private void init()

public void initrect(float x, float y, float width, float height)

public void clear()

else

childnodes = null;}}

}

1.預設構造的qtree樹節點都是葉子節點

2.物件只會放入葉子節點

3.每個葉子節點可以存放的物件上限是 maxchildcount,下同(在深度沒有達到最大值的情況下,否則不限

4.當葉子節點存放的物件數量超過 maxchildcount,則分離生成子樹(4個區域象限),並把自身儲存的所有物件存放到子樹中,然後標記為非葉子節點,清除自身所有儲存的物件引用

5.根據物件的座標及寬高插入qtree樹中(邊界物件可能會加入多個qtree樹中

/// /// 插入四叉樹

///

public void insertqtree(qtreenode, t t) where t : irect, imark

else

}else}}

/// /// 分離樹(象限)

///

private void splitqtree(qtreenode) where t : irect, imark

}/// /// 建立子樹(葉子節點)

///

private qtreecreatechildnode(float x, float y, float width, float height, int depth) where t : irect, imark

/// /// 查詢樹,並返回包含所有樹節點的列表

///

public void queryqtreeretrunlist(qtreenode, ref list> qtreelist) where t : irect, imark}}

/// /// 查詢樹,並返回包含所有樹節點的列表(按depth公升序排列)

///

public void queryqtreereturnriselist(qtreenode, ref list> qtreelist) where t : irect, imark

/// /// 獲取目標所在的象限索引列表

///

public int gettargetquadrantindex(qtreenode, t target) where t : irect, imark

if (isright)

return indexs;

}/// /// 返回目標周圍的可能碰撞物件列表

///

public void findtargetaroundobjs(qtreenode, t target) where t : irect, imark

}else}}

如上圖:黃色方塊為跟隨滑鼠移動的目標物件,綠色方塊為待與黃色方塊做碰撞計算的物件,紅色方塊為已發生碰撞的物件

下圖為最大深度4、根節點深度1,10000個物件的插入、查詢測試:

如上圖:10000個物件的四叉樹插入平均耗時14ms,查詢計算物件700多個大概5ms,300多個大概1.5ms

優化了如下兩個介面,移除了list造成的gc

1.優化了gettargetquadrantindex介面,移除了原有返回的list,改為int,位列舉儲存

2.新增了imark介面:用來標記待比較物件,findtargetaroundobjs後,在呼叫段通過for迴圈找出所有的待比較物件

呼叫段示例:

public class element : irect, imark

public colortype color

public bool ismoving

public float from_x

public float from_y

public float to_x

public float to_y

public float duration

public float x

public float y

public float width

public float height

public int mark

private float factorspeed;

private float factor;

public void init(int id, float x, float y, float width, float height)

public void move(float from_x, float from_y, float to_x, float to_y, float duration)

, duration = , from_x = , from_y = , to_x = , to_y = ");

this.from_x = from_x;

this.from_y = from_y;

this.to_x = to_x;

this.to_y = to_y;

this.duration = duration;

ismoving = true;

factorspeed = 1f / duration;

factor = 0;

x = from_x;

y = from_y;

}public void update(float deltatime)

else

}}

private void findtargetaroundobjs()

}if (objs != null && objs.count > 0)

calculatecollision(mouseuielement.m_element, objs);

for (int i = 0; i < muielementlist.count; ++i)

}else

resetelementcolor();

mouseuielement.setvisable(checkoutiscollision(mouseuielement.m_element, rootelement));

}

詳見原始碼:

Unity學習 十三 場景優化之四叉樹

四叉樹是在二維中定位畫素的唯一適合的演算法。因為二維空間 圖經常被描述的方式 中,平面畫素可以重複的被分為四部分,樹的深度由 計算機記憶體和圖形的複雜度決定。四叉樹 quad tree 是一種資料結構,是一種每個節點最多有四個子樹的資料結構。四叉樹可以用來在資料庫中放置和定位檔案 稱作記錄或鍵 這一...

四叉樹與八叉樹

前序 四叉樹或四元樹也被稱為q樹 q tree 四叉樹廣泛應用於影象處理 空間資料索引 2d中的快速碰撞檢測 儲存稀疏資料等,而八叉樹 octree 主要應用於3d圖形處理。對遊戲程式設計,這會很有用。本文著重於對四叉樹與八叉樹的原理與結構的介紹,幫助您在腦海中建立四叉樹與八叉樹的基本思想。本文並不...

四叉樹與八叉樹

前序 四叉樹或四元樹也被稱為q樹 q tree 四叉樹廣泛應用於影象處理 空間資料索引 2d中的快速碰撞檢測 儲存稀疏資料等,而八叉樹 octree 主要應用於3d圖形處理。對遊戲程式設計,這會很有用。本文著重於對四叉樹與八叉樹的原理與結構的介紹,幫助您在腦海中建立四叉樹與八叉樹的基本思想。本文並不...