生活随笔
收集整理的這篇文章主要介紹了
Unity实现BStar寻路
小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
BStarFindPath
- 歡迎了解BStar尋路算法
- 想象空間
- BStar尋路的優(yōu)勢(shì)
- BStar尋路的劣勢(shì)
- 路徑優(yōu)化的方案
- 空間優(yōu)化的方案
歡迎了解BStar尋路算法
BStar算法歸于人工智能或人工生命一類,是讓對(duì)象呈現(xiàn)出擁有生命一般,朝著目標(biāo)點(diǎn)移動(dòng)并繞開障礙物,如果目標(biāo)點(diǎn)被障礙物包圍則停留在附近點(diǎn)。
想象空間
可以將BStar尋路想象成一個(gè)朝目標(biāo)前進(jìn)的貪吃蛇,如果遇到障礙就會(huì)分裂成2條貪吃蛇,一左一右繞開障礙,繞開障礙后繼續(xù)向目標(biāo)點(diǎn)移動(dòng),只要有一條蛇到達(dá)目標(biāo)點(diǎn)即尋路結(jié)束。
這里我們需要三類蛇來(lái)滿足我們的設(shè)計(jì)需求:
自由蛇(向目標(biāo)點(diǎn)前進(jìn),遇到障礙會(huì)分裂成左轉(zhuǎn)蛇和右轉(zhuǎn)蛇)左轉(zhuǎn)蛇(只考慮繞著障礙左轉(zhuǎn),一直到繞出障礙變成自由蛇或者遇到已經(jīng)繞過(guò)的路消失)右轉(zhuǎn)蛇(只考慮繞著障礙右轉(zhuǎn),一直到繞出障礙變成自由蛇或者遇到已經(jīng)繞過(guò)的路消失)
可以想象在復(fù)雜的地形下,會(huì)出現(xiàn)很多蛇,最終先到終點(diǎn)的蛇就是我們要找的路徑。
下圖只有自由蛇 (2N - 10N) N代表自由蛇
下圖開始是自由蛇(2N-5N)撞墻后變成了左轉(zhuǎn)蛇和右轉(zhuǎn)蛇繞開障礙,繞開后變成自由蛇奔向終點(diǎn)。
BStar尋路的優(yōu)勢(shì)
目標(biāo)點(diǎn)在封閉空間內(nèi)時(shí),BStar效率優(yōu)勢(shì)明顯
目標(biāo)點(diǎn)在需要繞路的空間內(nèi)時(shí),BStar效率優(yōu)勢(shì)明顯
BStar尋路的劣勢(shì)
貼近障礙走的問(wèn)題嚴(yán)重,特別喜歡貼墻走。上文提到BStar算法歸于人工智能或人工生命一類在此處可見一斑,大家仔細(xì)觀察生活中很多人雖然繞路也是喜歡貼墻走的。
仔細(xì)觀察灰色部分BStar的原始尋路數(shù)據(jù),不難發(fā)現(xiàn)貼著墻走的問(wèn)題嚴(yán)重。
大局觀的缺失,因?yàn)锽Star尋到的不是最優(yōu)解
路徑優(yōu)化的方案
1、對(duì)尋得的原始路徑進(jìn)行smooth處理,提取其中的可行關(guān)鍵點(diǎn)以減少貼墻的問(wèn)題
下圖中黃色的點(diǎn)為關(guān)鍵路徑點(diǎn)
if (bstar_finded_src_way.Count >= 2){WayNode a = bstar_finded_src_way[L];pricallback_finded_one_way.path_way.Add(a);while (find_next == 1){find_next = 0;for (int j = L + 17; j > L; j--){if (j >= bstar_finded_src_way.Count) continue;WayNode b = bstar_finded_src_way[j];if (CheckPathLine(a, b) == true){a = b;L = j;find_next = 1;pricallback_finded_one_way.path_way.Add(a);break;}}}}
public void SmoothPath(){//Husunren 再次優(yōu)化路徑smooth處理,計(jì)算可達(dá)性,去掉中間的點(diǎn)int L = 0, ans = 0; //Husunren 這里的ans是為了迭代過(guò)深造成的性能問(wèn)題的優(yōu)化while (L + 2 < path_way.Count){WayNode a = path_way[L];WayNode b = path_way[L + 1];WayNode c = path_way[L + 2];if (ans < 7 && BStarPath.CheckOtherAnglePathLine(a, c) == true){path_way.Remove(b);ans++;}else{L++;ans = 0;}}}
2、對(duì)于BStar尋路沒(méi)有大局觀的優(yōu)化,可以加入途徑點(diǎn)的概念,上層先進(jìn)行一次大致位置的尋路,再由BStar來(lái)負(fù)責(zé)細(xì)致的尋路。
下圖是1000,000個(gè)格子的大世界尋路,先進(jìn)行一次洲的尋路計(jì)算出路徑點(diǎn),再由BStar進(jìn)行點(diǎn)到點(diǎn)之間的尋路
大家可以看到在1000x1000的地圖中,從左上尋路到右下,耗時(shí)是2ms左右,證明了BStar尋路性能的優(yōu)越。
空間優(yōu)化的方案
在格子數(shù)量過(guò)多的情況下,我們需要對(duì)尋路的數(shù)據(jù)進(jìn)行壓縮以達(dá)到比較合理的空間利用。
這里我采用了位壓里處理。將1,000,000個(gè)格子的數(shù)據(jù)壓到4mb的內(nèi)存中,以減少內(nèi)存的浪費(fèi)。
public struct BPathCell
{public int Reset_data;const int ResetData_Road_LT_Offset = 0;const int ResetData_Road_LT_Mask = 0x1 << ResetData_Road_LT_Offset;const int ResetData_Road_LB_Offset = 1;const int ResetData_Road_LB_Mask = 0x1 << ResetData_Road_LB_Offset;const int ResetData_Road_RB_Offset = 2;const int ResetData_Road_RB_Mask = 0x1 << ResetData_Road_RB_Offset;const int ResetData_Road_RT_Offset = 3;const int ResetData_Road_RT_Mask = 0x1 << ResetData_Road_RT_Offset;const int ResetData_BackDir_Offset = 12;const int ResetData_BackDir_Mask = 3 << ResetData_BackDir_Offset;public int back_dir{get{return ((Reset_data & ResetData_BackDir_Mask) >> ResetData_BackDir_Offset);}set{unchecked { Reset_data = ((Reset_data & ~ResetData_BackDir_Mask) | (value << ResetData_BackDir_Offset)); }}}const int ResetData_g_Offset = 16;const int ResetData_g_Mask = 0xFFFF << ResetData_g_Offset;public int g{get{return ((Reset_data & ResetData_g_Mask) >> ResetData_g_Offset);}set{unchecked { Reset_data = ((Reset_data & ~ResetData_g_Mask) | (value << ResetData_g_Offset)); }}}public int road_LT{get{return ((Reset_data & ResetData_Road_LT_Mask) >> ResetData_Road_LT_Offset);}set{unchecked { Reset_data = (int)((Reset_data & ~ResetData_Road_LT_Mask) | (value << ResetData_Road_LT_Offset)); }}}................
}
作者:胡孫仁
Author: HuSunren(FD.Creator) QQ: 75567044
email: aveking@qq.com aveking@163.com
Copyright ? 2020 tel: 18616334412
總結(jié)
以上是生活随笔為你收集整理的Unity实现BStar寻路的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。