unity中NavMesh的靜態(tài)生成與動態(tài)加載,以及踩坑與爬坑

unity 導(dǎo)航數(shù)據(jù)的靜態(tài)生成與動態(tài)加載

本文主要描述了如何使用更加方便的 高級NavMesh構(gòu)建工具,用以靜態(tài)烘培&動態(tài)更新網(wǎng)格數(shù)據(jù),還包括其中遇到的一些坑與爬坑指南丹莲。不包含一些基礎(chǔ)知識描述,基礎(chǔ)知識請看下面官方文檔。

導(dǎo)航功能為unity內(nèi)置功能堡僻,基礎(chǔ)知識與具體各個組件功能與使用可見官方文檔:
https://docs.unity.cn/cn/2020.3/Manual/Navigation.html

高級NavMesh構(gòu)建工具未內(nèi)置在官方包內(nèi)疫剃,需要從github導(dǎo)入使用钉疫。github倉庫地址:
https://github.com/Unity-Technologies/NavMeshComponents

1. 高級navmesh構(gòu)建工具

工具包內(nèi)主要包含這四個組件:

  • NavMeshSurface – 用于為一種代理類型構(gòu)建和啟用 NavMesh 表面巢价。
  • NavMeshModifier – 根據(jù)變換層次影響 NavMesh 區(qū)域類型的數(shù)據(jù)生成牲阁。
  • NavMeshModifierVolume – 基于體積影響 NavMesh 區(qū)域類型的數(shù)據(jù)生成。
  • NavMeshLink – 為一種Agent連接相同或不同的 NavMesh 表面壤躲。

除了上面的組件外城菊,工具包內(nèi)包含的Example工程內(nèi)也有一些腳本可以方便我們使用,例如后面會說到的navmesh動態(tài)更新使用到的 NavMeshSourceTag 碉克。
另外由于該工具包是完全開源的凌唬,遇到任何問題都可以斷點(diǎn)debug和直接修改源碼來解決;

2. 靜態(tài)烘培navmesh數(shù)據(jù)

使用 NavMeshSurface 組件進(jìn)行靜態(tài)烘培漏麦。

NavmeshSerface.png

  • AgentType: 選擇代理類型客税;
  • CollectObjects: 可選擇通過體積生成或子節(jié)點(diǎn)生成;
  • IncludeLayers:包含的Layer撕贞;
  • UseGeometry:通過mesh還是collider去確認(rèn)生成的范圍更耻;
  • DefaultArea:選擇默認(rèn)的區(qū)域類型;
  • OverrideVoxelSize(體素大心笈颉)和OverrideTileSize(區(qū)塊大兴重病)算是導(dǎo)航組件中常有的屬性,后面會詳細(xì)介紹;

最下面的Clear按鈕用來清理已生成的navmesh數(shù)據(jù)熬北;Bake用來烘焙疙描,點(diǎn)擊后會在同一文件夾下生成。


場景中的NavMeshSurface組件生成了導(dǎo)航數(shù)據(jù)

爬坑指南

點(diǎn)擊Bake按鈕生成數(shù)據(jù)成功后讶隐,打開Navigation面板會在場景中顯示已經(jīng)烘焙好的導(dǎo)航網(wǎng)格起胰。


失敗和成功的情況下,場景中的顯示

但很多時候由于某些操作不正確或者工具本身問題巫延,無法正常生成數(shù)據(jù)效五。如果生成后場景中沒有顯示導(dǎo)航網(wǎng)格,那么需要檢查下是否有以下情況:

  1. NavMeshSurface組件的節(jié)點(diǎn)是否是在場景中炉峰。預(yù)制體中烘培的數(shù)據(jù)會生成在Assets根目錄下畏妖,且如果場景中引用了預(yù)制體也無法生效。并且因?yàn)閳鼍爸泻皖A(yù)制體中都可以烘焙數(shù)據(jù)疼阔,且數(shù)據(jù)在不同目錄戒劫,如果開發(fā)者不熟悉,管理不妥婆廊,則非逞赶福可能造成數(shù)據(jù)冗余;
  2. clear按鈕偶爾會無法刪除掉舊的烘焙數(shù)據(jù)淘邻,再次生成時會生成了重復(fù)的副本茵典,所以需要檢查不要生成過多重復(fù)導(dǎo)航數(shù)據(jù),或者自行修改保存邏輯宾舅,強(qiáng)制刪除備份统阿;
  3. 在沒有以上問題的前提下,如果出現(xiàn)無法烘焙出數(shù)據(jù)的情況筹我,則切換下CollectObjects選項(xiàng)就可以了扶平。應(yīng)該是刷新機(jī)制有問題;

3. 動態(tài)加載navmesh數(shù)據(jù)

游戲進(jìn)入時導(dǎo)航網(wǎng)格數(shù)據(jù)初始化很慢崎溃,在進(jìn)入游戲時加載較大的網(wǎng)格數(shù)據(jù)時蜻直,普通配置的手機(jī)上甚至?xí)霈F(xiàn)卡住十幾秒的情況。

跟著場景一次性加載較大的網(wǎng)格數(shù)據(jù)袁串,除了初始化慢與占用內(nèi)存外概而,有時候還不能很好滿足業(yè)務(wù)需求。所以將較大的網(wǎng)格按功能分割成小塊囱修,在使用時再動態(tài)更新網(wǎng)格數(shù)據(jù)赎瑰,也是一個必不可少的處理方式。

動態(tài)更新navmesh數(shù)據(jù)可以參考高級構(gòu)建工具里的 NavMeshSourceTag 的使用破镰,其主要邏輯分為:

  1. 掛載NavMeshSourceTag組件的節(jié)點(diǎn)初始化時會把該節(jié)點(diǎn)記錄在NavMeshSourceTags中餐曼;
    void OnEnable()
    {
        _meshFilter = GetComponent<MeshFilter>();
        if (_meshFilter != null)
        {
            NavMeshSourceTags.Add(this);
        }
    }
  1. NavMeshSourceTag.Collect() 將記錄的所有Tags處理為官方接口使用的NavMeshBuildSource類压储。
public static void Collect(ref List<NavMeshBuildSource> sources)
{
    sources.Clear();
    for (var i = 0; i < NavMeshSourceTags.Count; ++i)
    {
        var mf = NavMeshSourceTags[i];
        if (mf == null) continue;

        var m = mf._meshFilter.sharedMesh;
        if (m == null) continue;

        var s = new NavMeshBuildSource();
        s.shape = NavMeshBuildSourceShape.Mesh;
        s.sourceObject = m;
        s.transform = mf.transform.localToWorldMatrix;
        s.area = 0;
        sources.Add(s);
    }
}

在實(shí)際的項(xiàng)目中,我將上面代碼里的 s.area = 0; 替換為根據(jù)NavMeshSourceTag組件內(nèi)新加一個變量Area源譬,這樣在組件節(jié)點(diǎn)上自定義集惋,動態(tài)更新生成不同Areas的導(dǎo)航數(shù)據(jù);

給官方腳本添加選擇Area的功能

  1. 手動調(diào)用RefreshNavMesh(),具體邏輯見代碼與注釋
    // 根據(jù)第一步中收集的Tag生成List<NavMeshBuildSource>數(shù)據(jù)
    NavMeshSourceTag.Collect(ref _sources);
    // 填寫navmesh構(gòu)建設(shè)置參數(shù)
    NavMeshBuildSettings defaultBuildSettings = NavMesh.GetSettingsByID(0);
    defaultBuildSettings.agentRadius = 0.01f;
    defaultBuildSettings.voxelSize = 0.001f;
    defaultBuildSettings.overrideVoxelSize = true;
    // navmesh可構(gòu)建空間踩娘,空間內(nèi)包含的才可生成導(dǎo)航數(shù)據(jù)
    var bounds = QuantizedBounds();
    // 選擇異步或者同步更新navmesh
    if (isAsync)
    {
        return NavMeshBuilder.UpdateNavMeshDataAsync(_navMesh, defaultBuildSettings, _sources, bounds);
    }
    else
    {
        NavMeshBuilder.UpdateNavMeshData(_navMesh, defaultBuildSettings, _sources, bounds);
        return null;
    }

爬坑指南

游戲運(yùn)行中刮刑,如果動態(tài)更新發(fā)現(xiàn)場景中沒有生成導(dǎo)航數(shù)據(jù),則需要檢查以下部分:

  1. 上面步驟3的代碼中养渴,bounds范圍是否包含需要動態(tài)更新的節(jié)點(diǎn)雷绢;
  2. 異步更新不會立即更新,需要一定的時間處理理卑;
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末翘紊,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子藐唠,更是在濱河造成了極大的恐慌帆疟,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,941評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件中捆,死亡現(xiàn)場離奇詭異鸯匹,居然都是意外死亡坊饶,警方通過查閱死者的電腦和手機(jī)泄伪,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,397評論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來匿级,“玉大人蟋滴,你說我怎么就攤上這事《灰铮” “怎么了津函?”我有些...
    開封第一講書人閱讀 165,345評論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長孤页。 經(jīng)常有香客問我尔苦,道長,這世上最難降的妖魔是什么行施? 我笑而不...
    開封第一講書人閱讀 58,851評論 1 295
  • 正文 為了忘掉前任允坚,我火速辦了婚禮,結(jié)果婚禮上蛾号,老公的妹妹穿的比我還像新娘稠项。我一直安慰自己,他們只是感情好鲜结,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,868評論 6 392
  • 文/花漫 我一把揭開白布展运。 她就那樣靜靜地躺著活逆,像睡著了一般。 火紅的嫁衣襯著肌膚如雪拗胜。 梳的紋絲不亂的頭發(fā)上蔗候,一...
    開封第一講書人閱讀 51,688評論 1 305
  • 那天,我揣著相機(jī)與錄音埂软,去河邊找鬼琴庵。 笑死,一個胖子當(dāng)著我的面吹牛仰美,可吹牛的內(nèi)容都是我干的迷殿。 我是一名探鬼主播,決...
    沈念sama閱讀 40,414評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼咖杂,長吁一口氣:“原來是場噩夢啊……” “哼庆寺!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起诉字,我...
    開封第一講書人閱讀 39,319評論 0 276
  • 序言:老撾萬榮一對情侶失蹤懦尝,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后壤圃,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體陵霉,經(jīng)...
    沈念sama閱讀 45,775評論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,945評論 3 336
  • 正文 我和宋清朗相戀三年伍绳,在試婚紗的時候發(fā)現(xiàn)自己被綠了踊挠。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,096評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡冲杀,死狀恐怖效床,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情权谁,我是刑警寧澤剩檀,帶...
    沈念sama閱讀 35,789評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站旺芽,受9級特大地震影響沪猴,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜采章,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,437評論 3 331
  • 文/蒙蒙 一运嗜、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧共缕,春花似錦洗出、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,993評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽阱洪。三九已至,卻和暖如春菠镇,著一層夾襖步出監(jiān)牢的瞬間冗荸,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,107評論 1 271
  • 我被黑心中介騙來泰國打工利耍, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留蚌本,地道東北人。 一個月前我還...
    沈念sama閱讀 48,308評論 3 372
  • 正文 我出身青樓隘梨,卻偏偏與公主長得像程癌,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子轴猎,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,037評論 2 355

推薦閱讀更多精彩內(nèi)容