Unity的使用(四):预制体,创建地形和地形导航

前面介绍了Unity游戏引擎的基础功能,现在终于要进入到游戏开发中了。那么,一款游戏开发要有资源,这个一般是由美术提供的,我们只需要负责程序方面的事。那么,怎么将获得的资源应用起来呢?

一. 导入资源

Unity放置资源的地方,自然是Assets文件夹了,从外部导入的资源都放在这里。Unity支持这几类资源:

  1. 脚本:支持两种编程语言,CSharp(.cs)和UnityScript(.js);
  2. 图像文件:支持常见的图像文件,如BMP, TIF, TGA, JPG和PSD;
  3. 模型文件:支持FBX格式,也可以使用Unity自带的原生格式(.max, .blend, .mb和.ma);
  4. 音频文件:支持.mp3, ogg, .wav等;
  5. Unity自身的资源格式类型:如预制体(.prefab),场景(.unity),资源包(.unitypackage)等;
    导入这些资源的方式也非常简单,第一种是直接将目标资源拖到Unity工程场景的Project视图下;第二种则是在Project视图下右键导入。
    Unity的使用(四):预制体,创建地形和地形导航_第1张图片
    我们也可以将自己的作品导出为资源包分享给别人使用。

二. 创建预制体

预制体,是预先准备好的,可以重复利用的游戏物体,可以大大减轻开发的工作量。在我之前的文章里,也简单的提到了预制体在场景中的工作原理,简而言之,就是场景文件直接引用预制体原文件并加上修改部分后,在场景中实例化。

由于预制体的特性,很多游戏物体都是保存为预制体以方便后期使用。创建预制体也很简单:

  1. 直接将游戏物体从Hierarchy视图中拖到Project视图的Assets下的文件夹内;
  2. 先在Assets文件夹内新建一个预制体,然后再将对应的游戏物体拖到新建的预制体上;
    Unity的使用(四):预制体,创建地形和地形导航_第2张图片

下面展示一个场景中的预制体具有的功能:
Unity的使用(四):预制体,创建地形和地形导航_第3张图片
游戏物体对应的预制体丢失,往往是因为我们将其对应的预制体文件删除了才会导致变红。要想断开游戏物体和预制体之间的链接,可以选中游戏物体后,直接点击GameObject -> Break Prefab Instance完成。当然,及时删除不用的预制体,对减小包体还是十分必要的。

三. 创建地形

在Hierarchy视图中右键->3D Object->Terrain,会当前场景中创建一个默认地形。点击地形游戏物体,查看Inspector视图有1

Unity的使用(四):预制体,创建地形和地形导航_第4张图片
在Terrain组件里,Unity为我们提供了7个工具。每选择一个工具,下方都会显示具体的工具介绍和配合按键能起到的额外效果。下面简单介绍一下每个地形工具:

  1. 地面升高工具:选中后点击Scene视图中的地形游戏物体,会使点中的地方升高,按住shift使之降低。升高不能超过地形允许的最大高度,降低则不能低过0。Opacity决定升高的快慢。
  2. 平面升高工具:总体功能类似地面升高工具,但是多了一个下图红框内容Height。
    平面升高工具的额外内容
    在Height可以设定你地面升高的最大高度(因此可以制作一些山顶平台之类的),但同样不能超过地形允许的最大高度。按住shift则是对点中的地方高度取样,将Height设定为改高度。最右侧的Flatten按钮可以将整个地形设置为该高度(之前地形高度信息不会保留)。
  3. 地形光滑工具:可以抹平高度改变导致的棱角,可以让你创建的山体(深坑)更加光滑~~Opacity决定平滑的速度。
  4. 地面贴图工具:当地形没有贴图时,首个添加的贴图将作为默认贴图覆盖整个地形,之后添加的贴图则可以作为选项用笔刷往地形上刷。Opacity为贴图的透明度。
    Unity的使用(四):预制体,创建地形和地形导航_第5张图片
    Target Strength,可以决定和原地形的混合比例,做出两种地形交界处的效果。
    下图为添加一个新的地形贴图:
    Unity的使用(四):预制体,创建地形和地形导航_第6张图片
  5. 种树工具:见下图,一张图解决问题:
    Unity的使用(四):预制体,创建地形和地形导航_第7张图片
  6. 细节工具:多用来种花种草,界面功能和地形贴图工具面板一样(因为花草本身就是一张贴图)。而且细节工具除了可以添加贴图,还添加网格预制体(不带碰撞体的)。下面是增加一个新的“草”贴图:
    Unity的使用(四):预制体,创建地形和地形导航_第8张图片
  7. 地形设定工具:在这里,我们可以设置地形的长宽高,以及树,花草细节该怎么显示。
    Unity的使用(四):预制体,创建地形和地形导航_第9张图片
    Unity的使用(四):预制体,创建地形和地形导航_第10张图片
    之所以会有一个距离多远消失或者以低分辨率显示的设置,除了模拟现实中远处模糊近处清楚,还可以为游戏节约性能。这里还要注意的是,对于高度图,细节贴图和全局地形贴图分辨率的更改,将会清除当前所有与之相关的内容

四. 简单的地形导航

既然已经创建好了地形,那么地面上肯定要有能走的地方和不能走的地方,毕竟很多地方我们实际上没进行处理,不能让玩家进去,那么我们怎么限制玩家,让其只能在我们允许的地方移动呢?这个时候就要用到地形导航了。

Unity中的导航系统是由“A*算法”衍射拓展实现的,其中有一个专门用来实现寻路功能的Navigation系统,这个系统由三个组件和一个Navigation总控制面板组成

要进行地形导肮,需执行以下步骤:

1. 烘焙导航场景

将角色要行走的场景地形设为静态物体,在Static中勾选Navigation Static,这样该物体就能参与到导航地形的烘焙中。
Unity的使用(四):预制体,创建地形和地形导航_第11张图片
接着打开Window -> Navigation面板,选择Bake选项点击Bake,就能进行场景烘焙了,烘焙后会在该场景文件所处文件夹下出现一个和场景同名的文件夹,保存导航网格烘焙数据(烘焙后的光照贴图,反射信息,光照探针等的信息也都是放在这儿的),下图中的呈选中状态的"NavMe…"就是生成的导航网格文件。
Unity的使用(四):预制体,创建地形和地形导航_第12张图片

2. 设置Navigation总控制面板

上面只是初步实现了导航网格的烘焙,我们要想实现导航功能,还需要根据开发需要设置Navigation控制面板。

  • Navigation的Agents选项
    用来设置不同的导航网格代理类型 。(这是一个尚不清楚功能的选项,因为Unity提供的用户手册中的Navigation面板中并没有这个选项,目前只能使用其提供的Humanoid。先简单记录一下,以后了解后再来补全)。
    Unity的使用(四):预制体,创建地形和地形导航_第13张图片

  • Navigation的Areas选项
    在现实生活中,每种地形的移动消耗是不一样,比如你从A走到B,一条是马路但路程较远,另一条是沼泽路程稍近。我想绝大部分人都会选择走马路,即便它路程较远,但是它的移动消耗更低。Unity里面则是用Areas来表示这种特性。
    Unity的使用(四):预制体,创建地形和地形导航_第14张图片
    我们创建的所有参与导航系统烘焙的模型,默认都是“Walkable”。Cost为在该地形上移动单位距离所需的消耗点;在进行寻路时,导航算法会计算累加起来消耗点最低的路径(所以自动寻路往往会绕过沼泽泥地等)。

  • Navigation的Bake选项
    Unity的使用(四):预制体,创建地形和地形导航_第15张图片
    我们烘焙导航网格就是在这个选项中进行的,因此着重介绍一下:

    • Agent Radius: 代理的半径,决定寻路代理的中心点能距离墙壁,岩架等不可跨越的障碍物多近;
    • Agent Height: 代理的高度,当空间位置的高度小于代理高度时,Agent无法进入该空间位置。如低矮的房间等;
    • Max Slope: 代理能走上的斜坡角度,大于该角度的斜坡代理无法走上;
    • Step Height: 代理能够跨越多高的障碍物;
    • Generated Off Mesh Links: 自动产生Off Mesh Links跳跃线。在烘焙场景时,我们可以让场景中物体自动产生跳跃线,前提是该场景有静态物体启用Generate OffMeshLinks属性
      • Drop Height: 下落的高度,当位于一个平台上时,且距离下方地面高度大于StepHeight(否则可以直接跨下去)小于DropHeight,产生跳跃线落到下方地面上,即导航代理可以从这里跳下去落到地面上,在水平方向上该代理的位移为:2 x AgentRadius + 4 x VoxelSize2。设置该值应当稍微设置的大一点来避免偏差造成跳跃线不能生成,当值为0时表示禁用此功能。
      • Jump Distance: 跳远距离,当该平台周围有和它位于垂直高度差不超过一个VoxelSize,且间隙距离大于2 x AgentRadius小于JumpDistance的其它平台时,产生从该平台到那个平台的跳跃线,即导航代理可以从该平台处跳到另一个平台上。设置该值时最好在跳跃距离上加上2 x AgentRadius(考虑到自身大小)再大一点点,当值为0时同样表示禁用此功能。
    • Advanced: 高级设置
      • Manual Voxel Size: 手动设置立体像素大小,若启用,允许于下方Voxel Size手动设置立体像素的大小。这里需要详细了解一下导航网格的烘焙原理3(见注解2)。Voxel Size表示了导航网格再现场景几何结构的精确程度。
        一般情况下,Voxel Size的值默认为导航代理半径(agent radius)的三分之一,因为这样能在准确性和烘焙速度上获得一个较好的平衡(减小体素大小会增加存储消耗和场景建立时间,size推荐值为半径的两倍到八倍之间)。
        通常情况下该值时不需要我们手动设置的,但是当我们的导航代理本身就很小或者想要烘焙走廊角落等地形复杂的地方时,就需要人为增大或者减小VoxelSize值了,这时就需要勾选上该选项手动设置VoxelSize值了。
      • Min Region Area: 最小区域面积,当进行导航网格烘焙时,一些面积小于最小区域面积的独立导航网格将会被裁剪掉4
      • Height Mesh: 当进行导航烘焙时,导航网格只是接近于可行走地形,很多地形的特征会在导航网格建立时被忽略。比如楼梯在导航网格中就以一道斜坡的方式呈现出来,若你想你的导航代理在导航网格中位置信息呈现得更准确,你可以启用此属性HegihtMesh,当然,这也意味着更多内存消耗和烘焙时间花费。

    最下面两个按钮的功能,Clear为清除烘焙好的导航网格,Bake为生成烘焙网格。

  • Navigation的Object选项
    在Hierarchy视图中选中一个游戏物体,在Navigation面板的Object选项上就会显示该游戏物体的导航设置。
    Unity的使用(四):预制体,创建地形和地形导航_第16张图片
    Generate OffMeshLinks,当需要在烘焙场景时在该游戏物体上自动产生到其它地点的跳跃线时,启用此属性,否则导航烘焙时不会产生以该游戏物体为起点的跳跃线
3. 导航组件的使用

在进行介绍之前,需要说明的是每个版本的组件属性不同,至少我这个版本的部分导航组件和在网上看到的许多博客的不同。因此本介绍仅作参考,各位开发者请以实际开发效果为准。

  • NavMeshAgent组件:导航网格代理。要想让游戏物体在烘焙完的导航网格上实现导航功能,就需要添加NavMeshAgent组件。
    Unity的使用(四):预制体,创建地形和地形导航_第17张图片
    添加了NavMeshAgent组件之后,对应的游戏物体会自动添加一个碰撞圆柱(如下图)。
    Unity的使用(四):预制体,创建地形和地形导航_第18张图片

    • Agent Type: 代理类型。这里的选项是根据在Navigation面板的Agent选项里设定的代理来提供的。
    • Base Offset: 基本偏移,决定碰撞圆柱和游戏物体中心点在y轴上的偏移。
    • Speed: 速度(m/s),决定导航代理的最大移动速度;
    • Angular Speed: 转弯速度(°/s),模型始终以自身Z轴朝向前进方向(在放置模型时也要注意让模型面朝向Z轴正方向),当自身Z轴不与前进方向平行,则会以此处设定的数值转向;
    • Acceleration: 加速度,决定达到最大移动速度的快慢;
    • Stopping Distance: 停止距离,距离目的地多远时代理停止移动;
    • Auto Braking: 自动刹车,若启用,则代理将在到达目的地后减速;
    • Radius: 半径,此值将决定碰撞圆柱的半径大小;
    • Height: 高度,此值将决定碰撞圆柱的高度值;
    • Quality: 躲避障碍物的质量。当有大量导航代理时,可以通过降低避障质量来节约CPU性能。当被设置为None时,只会进行碰撞处理但不会主动尝试的躲避其它代理和障碍物;
    • Priority: 该导航的优先级,对于优先级低于此代理的其它代理,此代理在进行导航时会忽略而不尝试躲避;这个值范围为0-99,较低的数值意味着更高的优先级;
    • Auto Traverse OffMeshLink: 当被启用时,允许自动穿过分离网格跳跃线,当你需要使用动画或者一些特殊效果来穿越分离网格跳跃线时,禁用它;
    • Auto Repath: 当被启用时,导航代理到达导航路线中某些节点时,将尝试重新规划导航路线;当没有到达目标点的路线时,将会规划一条到离目标点最近位置的路线;
    • Area Mask: 地形遮罩,地形遮罩将会决定导航代理在寻路时会考虑哪种地形;比如可以让某些角色不能通过某种地形;
  • OffMeshLink组件:分离网格跳跃线。当我们场景中存在两块独立的烘焙导航区域时,角色要想在两块区域间继续导航的话,就需“一座桥梁”来连接两块区域。
    Unity的使用(四):预制体,创建地形和地形导航_第19张图片

    • Start/End: 用来设置“跳跃线”的开始点和结束点,两点之间自动形成跳跃线;
    • Cost Override: 代价覆盖,定义导航代理通过该跳跃线花费的代价。默认值为-1,表示不需要花费代价。注意,此处设定的值会覆盖在Navigation Area参数中对应地形的花费代价;
    • Bi Directional: 如果启用,则该角色可以在两点之间来回跳跃移动;若不勾选,则只能从开始点跳跃到到结束点;
    • Activated: 设置该跳跃线是否激活可用,选中Navigation面板的情况下在Scene视图中会显示出烘焙好的导航网格和跳跃线,激活状态的跳跃线为深蓝色(黑色),未激活为暗红色;
    • Auto Update Position: 自动更新位置,若启用,则我们在运行的状态下,也可以对该跳跃线的开始点和结束点位置动态改变,跳跃线也会随之自动更新;

    使用OffMeshLink的注意事项:

    • 开始点和结束点不需要静态,因为“跳跃线”不需要参与到Navigation的导航网格烘焙;
    • 在Scene视图中,开始点和结束点若处于导航网格内会显示为两个圆圈,表示该跳跃线可用,若是离导航网格太远圆圈会消失,说明跳跃线不成立,需要重新调整对应点的位置;
  • NavMeshObstacle组件:导航网格障碍物,既是一些导航无法通过的区域或物体。一般情况下,是需要将这些障碍物设置为静态一起参与Navigation的导航烘焙,这样就可以在导航时避开障碍物了。但是,对于动态的障碍物就无法设置静态,也无法烘焙到导航网格之中,这个时候就需要Nav Mesh Obstacle。Unity的使用(四):预制体,创建地形和地形导航_第20张图片

    • Shape: 形状,控制障碍物的形状,可以选择是Box(盒子)或Capsule(胶囊体)。
    • Center: 中心点,碰撞体中心点位置相对于该游戏物体的偏移;
    • Size: 碰撞体的大小,可以控制控制碰撞体进行缩放;
    • Carve: 雕刻,一个相当消耗性能的参数,在不启用的情况下,该障碍物只是阻挡了物体前进路线,并没有改变物体导航网格,物体不会绕过该障碍物进行导航(即若该障碍物位于最短路径上,那么导航代理就会一直碰墙);若启用则会影响到导航网格,效果等同于静态障碍物,会在网格上“挖”出一块区域表示该区域无法通过,导航代理在导航时会绕过该区域。Carve下的属性有:
      • Move Threshold: 导航网格不是每一帧都在计算的,该参数表示只有当该障碍物移动的距离超过该参数时,才会重新计算导航网格;
      • Time To Stationary: 障碍物静止不动多久后重新计算导航网格(受下一个参数影响);
      • Carve Only Stationary: 若不启用,则当障碍物移动超出MoveThreshold后立刻重新计算导航网格,然后再以该位置重新计算移动距离;若启用,则当障碍物移动超出MoveThreshold后,还需要静止TimeToStationary时间后,才会重新计算导航网格。

  1. 编辑地形时,如果灯光渲染是自动进行的,那么每一个对地形的操作都会导致重新进行一次渲染,对于性能较低的电脑会使之操作严重卡顿,可在Window -> Lighting -> Settings -> Auto Generate设定是否自动渲染。 ↩︎

  2. 之所以要加上4 * VoxelSize,是因为从平台下落后往往为山崖下的角落,当导航代理位于角落等狭小地点时,会流出4个体素的空隙。 ↩︎

  3. 导航网格的烘焙过程是使用体素化来从任意的地形网格建立起导航网格的。在算法的第一步,场景将会被光栅化立体元素,然后可以行走的表面将被提取出来,最后可行走区域将被转化为导航网格。 ↩︎

  4. 但是并不是所有情况下都能成功裁剪掉面积小于MinRegionArea的那些小块的导航网格的。导航网格在建立时,是类似于一块一块平行的瓦片往上贴的,如果那块小的原本应该被裁剪掉的导航网格超出了瓦片的边界,那么那块导航网格不会被裁剪掉,因为裁剪发生在周围的瓦片无法获取的建立过程中。 ↩︎

你可能感兴趣的:(#,使用Unity开发游戏,unity)