Unity2d 遮蔽和障碍物系统原理及障碍物副本地图实现

发表于2017-05-08
评论1 6.8k浏览

  大多数2d游戏会有遮蔽和障碍物系统,这样处理后的游戏场景才会更显真实,但对于它的原理又有多少人知道,下面是给大家介绍下Unity2d遮蔽和障碍物系统原理,并通过一个障碍物副本地图的实例让大家更能清楚的去认识它。


背景
     虽然我玩过各式各样的游戏,但对于2d游戏中的遮蔽和障碍物系统,总有一种不识庐山真面目,只因身在此山中的感觉,总觉得是这么自然和理所应当,特别是对于障碍物系统更是这样,比如说高山不能跨越河流不能通过的,也许是和中国的教育有关,我们在做一件事情的时候,很少会问为什么?对于2d游戏中的遮蔽和障碍物系统,当自己尝试着去开发和实现的时候,才意识到,他们是真实存在的,在这个时候自己才会反思,为什么2d游戏中会存在遮蔽和障碍物?首先,障碍物还是比较自然和好理解的,就像刚才举的例子一样,不可能爬到高山上去和凭空穿过河流,好了,说了这么多废话,让我们进入正题,关于遮蔽和障碍物的原理基础是这样的,首先人类是生活在真实的三维世界,2d系统实际上是一种简化的三维模拟系统,当然简化的就是高度值,在这个模拟系统中,为了让玩家模拟得更加真实,基本会采用一种上帝视角,也就是我们是从上方俯视观看这个系统,这样自然就会产生一个问题,如何在2d系统中模拟3d系统的高度呢?这就需要一定的技巧来欺骗我们的大脑,我们通过 图示的方式来举一个例子,在游戏世界中有一棵树,首先角色不能走到树上,这样的树本身就一定会是一个不能通过的障碍物,也就是角色不能达到的坐标;其次,不能为了达到不能产生人走到树上的效果。人走到树下的时候,通过上帝模式观察,视觉几何透视原理,人当应该在树的背面,也就是被树所遮挡,这就是我们所提到的2d系统遮蔽和障碍物系统了,原理说了这么多,我想大家也应该明白了,接下来就是如何通过程序来实现了。

 


实现
     首先我们先来实现遮蔽系统,由于目前流行的引擎一般是通过显卡来实现所以都拥有高度值,也就是z值,Unity2d更是如此,本来就是3d的简化版本而且有相机的概念,也就是我们所说的上帝模式是摄像机所看到的视口,这样我们在场景中调整不同精灵的z值,就很容易实现不同深度的遮蔽,有了这么强大的工具,实现一个完美的遮蔽系统就变得很容易了,不像以前的2d引擎可能还需要通过渲染的顺序来完成这 个功能,具体实现如下图所示,

我们在2d系统中设置Z值就可以了。

     接下来我们来说一下障碍物系统,谈到障碍物系统,就不得不说系统的寻路算法,因为障碍是寻路算法的基础,如果没有障碍也就没有必要做寻路了,当然目前可以选择到寻路算法非常多,可以选择A*或者网格来进行寻路,关于A*寻路算法的文章很多,具体的原理是将地图转换成网格矩阵,通过网格矩阵来标识是否是障碍物,沿着这个思路往下走,由于地图很大障碍物是随 着场景地图的里面元素来确定的,复杂地图的寻路和障碍物必须通过地图编辑器来实现,所以很多游戏本身都自带地图编辑器,其中很重要的一环就是设置地图中的障碍物系统。
    这里我们借助深蓝色右手的思路,换一下思路,通过另一种方式来实现障碍物也就是副本地图,当然这里所说的副本地图是指的游戏场景分层地图,不是我们熟知的魔兽世界中的副本场景,具体原理如下图 
所示,

实际上,场景地图可以分很多层,简单的有背景地图层,遮蔽层,副本地图层也就是障碍物层。
这里我们看到障碍物使用不同的颜色来表示出,这样我们只要通过屏幕图层取色算法,图层中赋予不同的颜色就可以实现不同的游戏逻辑原理,比如说是否可以移动到,传送点,飞行地图等等,这真是一项神奇的技术,下面给出图层取色的详细代码,提供给大家参考。

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
if (Input.GetMouseButton(0))
      {
          Vector3 worldPoint = Camera.main.ScreenToWorldPoint(Input.mousePosition);
          RaycastHit2D hit = Physics2D.Raycast(worldPoint, Vector2.zero);
  
          if (hit.collider != null)
          {
              Debug.Log("Target Position: " + hit.collider.gameObject.transform.position);
              //and do what you want
              SpriteRenderer bg = hit.collider.gameObject.GetComponent();
              Texture2D t2d = bg.sprite.texture;//读图片资源
              Color c = t2d.GetPixel((int)Input.mousePosition.x, (int)Input.mousePosition.y);//获取图片xy坐标处的颜色
  
              Debug.Log("color: " + c + " mousePosition : " + Input.mousePosition + " w:" + t2d.width + " y:" + t2d.height);
          }
 }

  实际原理很简单就是一个碰撞检测,然后加上Texture2d的像素取色就可以了。这里别忘记了设置取色sprite的boxcollider和texture type为 advance(不然不能使用GetPixel)


总结
     当然在实际中的遮蔽系统可没有这么简单,我也会在后续的文章中给出思路和实现,有时候我也在反思,当人在儿童期的时候总是会问很多为什么?但成年以后我们就不这么做了,也就慢慢 失去了思考的源泉,之前关于寻路算法的系列文章,很多同学留言说看不懂,我仔细想了一下这个问题,实际上也是很正常的,就和看书是一样,我想作者在写书的时候,一定经过学习实践思考总结的过程,最终才形成文字,还需要反复修订和修改,这个过程是一个很耗时耗力的工作,也是一种学习的过程,所以说当付出时间和精力不等的情况下,获得知识的多少也是成正比的,所以通过短短的阅读文章的时间来掌握某个知识点,特别是还不通过动手来实践,反复思考,可能确实是有点困难!当然也可能与作者的水平和语言组织能力有关。所以说呢!对于大家来说是一样的,革命尚未成 功,同志仍需努力!


如社区发表内容存在侵权行为,您可以点击这里查看侵权投诉指引