U3d開發中大部分事件都是用數學進行計算判定的嗎?

根據我們老師所講 ,真正的開發中用到碰撞體,碰撞器進行事件判定的話會佔用大部分資源會使遊戲運行起來非常卡頓,所以最好使用數學去進行計算判定。這種說法正確嗎?另本人數學幾何方面極爛。。。有關於3d數學方面較為入門一點的書籍嗎?


想了半天怎麼回答這個問題,樓主看來並沒有實際開發經驗,講太抽象沒什麼益處。就舉個例子說明吧。

一個很簡單的問題:獲得角色前方扇形區域內的敵人。這個無論是潛入類遊戲(模擬AI的視野範圍),還是國產網遊的刀光、劍氣,還是MOBA遊戲里都有用到。

重述一下這個問題:獲取角色前方扇形區域內的所有敵人。那麼,解決這個問題有什麼方法呢?

1、多射線檢測。

這個是我們的專欄《遊戲開發入門指南》里AI相關係列的一張圖,借來一用。紅色扇形區域是由射線組成的,這種做法好寫好用,用在小遊戲里沒什麼性能問題,因為小遊戲里物體並不多,毫無壓力。但是它除了射線越多越慢的問題,還有一個缺陷,射線之間是有間隔的,距離遠了以後,兩條射線之間可能會漏過一些特別小的物體。要想不漏,只能增加射線熟練,弊端很嚴重。

2、Overlap檢測

譬如Unity的Physics.OverlapSphere函數可以避免使用碰撞器、射線來檢測一個球形範圍內的碰撞體。先調用它,會得到一個Collider[],也就是碰撞體數組。然後挨個看碰撞體是否在扇形範圍內。

判斷物體是否在扇形內的方法:

如圖,已知玩家自己的forward向量,也就是指向玩家前方的單位向量;還知道玩家位置和敵人位置,可以得到v1向量,那麼只要求兩個向量的夾角,就可以知道它是不是在扇形區域內。求夾角用向量點積公式即可,不再贅述。Unity裡面有Vector3.Angle可以方便使用。

這個方法極其重要,在本問題中是核心演算法。無論你怎麼優化,最終都要用到這個方法。

3、在小場景的前提下,徹底摒棄碰撞檢測。

如果是開房間式的遊戲,例如《皇室戰爭》,一場戰鬥內的物體極少,那麼只要手動依次判斷每一個物體離角色的距離,反而可能效率更高。和每個物體判斷距離以後,在某個距離內的物體就是圓形或者球形區域內的東西了,問題就和上面的方法2完全相同了,略過。

其實同理,在上圖這麼小的場景內,所有碰撞檢測可能都是可以去掉的,完全沒有必要了。只要自己定義一種獲取範圍內物體的方法,就可以處理所有碰撞問題了,比用引擎自帶的通用碰撞檢測可靠多了。

4、大場景怎麼辦?

很簡單,大場景可以化歸為小場景。無論是《魔獸世界》還是《尋仙》,任何大型網遊都有「玩家同屏表」的概念,所謂「同屏表」,就是距離玩家一定範圍內的一個矩形或者圓形區域內的所有角色、可交互物體的列表,只看這個列表內的所有東西,就和方法3討論的「小場景」是沒有區別的。

如上圖,無論東西有多麼多,檢測碰撞的時候都可以很好地劃歸到小範圍內,不會帶來性能問題。如果你直接用通用的碰撞檢測機制,可能要炸 XD。

注意,這裡討論的已經超出客戶端範圍了哦,這種碰撞檢測在伺服器上也是要運作的,特別是國產網遊在反外掛方面不遺餘力,所有的碰撞都會在伺服器上計算,想想都很恐怖。但其實這個計算壓力在使用了合適的方法後,計算量並沒有想像中那麼大,是十年前就被解決了的問題。

關於四叉樹

同屏表本身的存在是否會帶來性能問題呢?其實網遊一般不僅提供角色同屏表,還可以快速獲得大地圖上任意矩形範圍內的所有物體。這是因為網遊為了管理大量對象(同場景以萬為量級),使用了四叉樹,可以使用很少的內存很有效地管理大量對象(如果用純數組會爆的)。同屏表的實現和它也有關係,換句話說四叉樹改良了同屏表的實現。

我這是從一個非常小的側面,一個具體的小問題,來解釋了實際遊戲中碰撞檢測是怎麼實現,怎麼優化的。如果你是做小遊戲、小Demo,大可不必大費周章,就直接觸發器搞定一切。但是如果在團隊中工作,做一個有規模的項目,那麼優化就必不可少了。推薦一本書,很好用,也不算難:

順帶補充一句: 碰撞盒的檢測引擎內部 不也是數學計算么, 所以這題問的還是有些怪的。 對於一個3D虛擬空間來說,沒有數學,就沒有一切。


Unity中的collider是為了通用性設計的,不管什麼類型的遊戲,給個collider組件就能用,開發者不需要考慮內部的細節。而collider實際上也是數學計算,但是為了保證各種形狀的多邊形都能正常檢測,內部做了很複雜的運算。

而實際開發中我們可以使用簡化的數學計算來檢測碰撞,滿足需求即可。這種碰撞檢測是滿足單一類型遊戲設計的,因此性能會比unity自帶的要好許多。

如果遊戲中的所有碰撞體都是圓形,比如球球大作戰這類遊戲,遍歷比較每兩個圓心的距離和兩個圓半徑之和即可,如果比較圓心距離平方的話還能省去開根號的計算。若場景足夠複雜,還可以使用四叉樹或八叉樹(3D)進行空間劃分,提高性能。當場景中碰撞體不多的話就不要使用四叉樹八叉樹優化了,空間劃分的時間可能會比碰撞檢測的時間還要長。

再比如打磚塊遊戲,由於磚塊都是垂直或者平行的面,只需要遍歷所有方塊的每一條邊,帶入公式檢測直線是否與圓相交即可。

Moba遊戲中扇形檢測可以通過點乘來判斷角度,再判斷一下距離就可以。

以上是本人的一點心得體會,也是新手,有不對的地方希望指正。


碰撞體不也是數學么,嚴謹一點的說法是自己實現,不依賴引擎,很多公司只是把unity作為一個畫面表現工具而已,因為他們有自己的積累,底層都是自己實現的


最佳通用選擇就是用碰撞體來判斷。如果你自己寫也是寫八叉樹來處理,一樣的演算法寫出來肯定沒unity的效率高。所以就用碰撞體吧。如果基本(box,sphere)碰撞體滿足不了的(例如:錐形判斷、速度太快等),可以使用自己寫的演算法。


推薦閱讀:

為什麼對球的體積公式進行求導會得到球的表面積公式?
為什麼星系的邊緣會「翹」起來?
什麼是包絡線?包絡線又是如何繪製的?
在一個由n x m個正方形格子組成的的矩形上畫一條這矩形的對角線,這線段將穿過多少個格子?
在一個正方體中按以下規則反覆連線,最後會連出多少個交點?

TAG:遊戲開發 | 幾何學 | Unity遊戲引擎 | 計算機圖形學 |