zoukankan      html  css  js  c++  java
  • 进击的新版NavMesh系统:看我飞檐走壁

    0x00 前言

    unity5.6作为Unity5最后的一个版本,的确起到了一个承上启下的作用。除了上一篇文章《进击的AssetBundles和它的工具们》中提到的AssetBundles-Browser,本文还会介绍另一个在Github开源的,用于Unity5.6+的新寻路功能。

    0x01 曾经的痛点

    Unity5.6之前的navmesh系统的确操作起来十分容易上手,门槛很低。我们只需要将场景内需要烘焙navmesh的区域勾选上Navigation Static选项,之后就可以在Navigation窗口中烘焙整个场景了。

    QQ截图20170717135759.png

    但是曾经的navmesh系统却也存在着一些性能上的和使用场景上的缺陷。
    一个常见的问题,由于要预先烘焙场景的navmesh,因此我们很难方便的在运行时动态的修改navmesh。更不用说,有一些游戏的场景并非提前制作好的,需要在运行时动态的生成,这种情况下就无法使用navmesh了。
    另一个问题是,如果场景过大的话,烘焙之后的navmesh也会保存很多数据,在运行时会造成一些内存上的开销。
    当然,抛开这些不谈,另外一个让我吐槽navmesh的一点就是,它竟然不支持垂直面的导航。

    donkey-kong-screenshot.jpg

    在做一些2d的platform游戏时,我很希望能利用navmesh来实现寻路的逻辑。(图文无关)
    但是,不幸的是,之前的navmesh是不支持的。
    QQ截图20170717151840.png

    0x02 组件化的navmesh

    不过还好,虽然新的navmesh系统并没有随着unity的正式版本一同发布。但是,我们还是可以通过github来获取这些新的功能:

    NavMeshComponents

    需要注意的是,Unity的版本要求在5.6以上。

    我们可以看到,其实这里只有4个高层的C#脚本文件:

    QQ截图20170717161301.png
    利用这4个脚本文件,就能基本解决我们之前的烦恼了。

    其中NavMeshSurface这个脚本将navmesh组件化,利用这个组件就可以很方便的烘焙挂载该组件的对象的navmesh信息,而无需打开一个navigation窗口对整个场景进行烘焙了。我们甚至可以将挂载这个脚本的GameObject烘焙后保存为一个prefab,这个带有navmesh信息的prefab跟其他的prefab一样。

    1.gif
    为对象添加NavMeshSurface组件很简单。在这里我们可以看到和之前navigation窗口类似一些设置,但是请注意,这里已经不是整个场景烘焙了。navmesh已经组件化了,它只会烘焙挂载它的对象。

    2.gif

    只要点击一下这个组件下的Bake按钮,挂载它的对象就被烘焙好了。
    那么GameObject能否挂载多个NavMeshSurface组件呢?这一种需求也的确存在,例如怪物和玩家的寻路策略不同,有些地方玩家能通过而怪物却不能通过。
    这的确也是可以的,同一个GameObject能够同时挂载多个NavMeshSurface组件,并且烘焙不同的navmesh供不同的角色使用。

    5.gif

    这样,我们针对不同的角色的NavMeshAgent组件设置不同的agent type并和烘焙好的两个navmesh匹配好就可以了。

    0x03 飞檐走壁

    好了,借助NavMeshSurface组件我们实现了navmesh的组件化。那么是不是我们就能很方便的实现在垂直面上烘焙navmesh了呢?各位想想我们是否能很轻松的让一个游戏对象的角度改变呢?答案是是的。那么这个游戏对象上如果有navmesh信息的话,我们只需要把这个游戏对象从水平变为垂直是否就行了呢?是的。
    因此实现游戏角色的在垂直面上飞檐走壁的功能就变得十分简单了。

    120111111.gif
    当然了,在水平面的navmesh和垂直面的navmesh之间我们还会用到NavMeshLink这个组件来链接二者。各位自己在实践的时候需要留意一下这一点。

    0x04 在运行时烘焙navmesh

    接下来就让我们看看新的navmesh系统带给我们的新的惊喜——在运行时烘焙navmesh。
    这是一个很现实的需求,例如一些动态生成场景的游戏,我们无法在一开始就确定这个场景到底是什么样子的,所以也无法使用之前的navmesh系统,因为以前的navmesh只能在editor内烘焙。但是现在我们使用新的navmesh系统就能够很方便的在运行时烘焙navmesh了。

    120111.gif
    如图,这是一个空场景,在游戏运行之后场景才生成出来场景内的各种道路,此时单击鼠标,navmesh就生成了。
    其实在新的navmesh系统内,实现这个机制十分简单。只需要调用游戏对象上挂的NavMeshSurface组件的BuildNavMesh()方法。

    void Start()
    {
    	surface = GetComponent<NavMeshSurface>();
    }
    
    void Update()
    {
    	if (Input.GetMouseButtonDown(0))
        {
    		surface.BuildNavMesh ();
        }
    }
    

    既然navmesh已经可以在运行时创建了,那么我们能否也在运行时实例化一个navmesh的prefab,实时的影响场景内的寻路策略呢?
    答案是当然可以。

    0x05 场景太大不用愁

    自己做过寻路算法的童靴可能会意识到一个问题,就是在做寻路时如果场景过大的话,寻路的数据可能会比较消耗内存。同样在navmesh中,如果场景过大,或者玩家的视野范围有限,一些对玩家当前位置影响不大的场景的其他位置的navmesh数据就有可能造成一些无谓的消耗。
    在新的navmesh系统中,我们同样可以优化这个问题,只烘焙玩家周围的navmesh。
    EADTwTIM3A7bpEsOJ6nCkQgV2rQRzzVh.gif
    这里同样需要NavMeshSurface组件,在inspector视窗我们可以选择collect object中的volume,之后设定size的值就可以值烘焙这个范围内的navmesh了。之后随着玩家的移动,再动态烘焙新的navmesh就可以了。

    0F5wYAckNZOcc3vNPSKD6GqAmj09MKYt.gif

    ref:

    【1】High-level NavMesh Building Components
    【2】Unite Europe 2017 - Finding the path: New navigation features

    各位如果觉得有趣的话,欢迎点个赞。

    -EOF-
    最后打个广告,欢迎支持我的书《Unity 3D脚本编程》

    欢迎大家关注我的公众号慕容的游戏编程:chenjd01

  • 相关阅读:
    Python基础学习Day2
    Python基础学习
    字符串
    function对象
    GCN入门理解
    L1、L2正则化详解
    Matplotlib数据可视化基础
    sklearn 中模型保存的两种方法
    一文弄懂神经网络中的反向传播法——BackPropagation
    seaborn可视化
  • 原文地址:https://www.cnblogs.com/murongxiaopifu/p/7196788.html
Copyright © 2011-2022 走看看