跟我一起用unity做小地图!

lol的小地图

lol的小地图

转载爬虫请自重,未问先转没排面

不爱多做铺垫,小地图对于一些游戏来说多重要大家都懂,不然你也不会来看我这篇文章的,对不对?

话不多说,开搞!

一、主体功能

一般来说,游戏里的迷你地图都是平面的。但是,默认的摄像机模式,即perspective(透视),是得不到这样的效果的。那怎么办?使用orthographic(正交)模式就好啦。

修改后,控制视野的参数由Field of View变成了Size

选择性显示

如果把游戏中的所有东西都在小地图上渲染一遍,难免显得杂乱,失去了小地图的简明扼要这个特点。那怎么办呢?

可以选择使用Layer(图层)来实现选择性显示。即给需要显示的物体加上特定的图层,这样的话,就可以在小地图里只显示具有指定图层的物体啦。

最简单的做法,给要显示的物体加上图层showInMiniMap,只在迷你地图中渲染这些物体就可以了。但是呢,我不会这么做的...因为我衡量了一下,其实大部分物体都是要渲染的,所以...你懂得,我们给无需渲染的物体加上图层hideInMiniMap,然后过滤掉他们就好了!

这个 showInMiniMap后面还有用处。

引申:给NPC加上特定标记

举一反三是一个很好的习惯,相信有些机智的小伙伴已经能想到了。如果给特定的NPC加上特定的图层,是不是就可以在地图上显示不同的标记呢?

比如:

  • 敌人:红色点点
  • 自己:绿色长三角(三角尖指向当前朝向)
  • 商店老板:金袋icon
  • 装备升级:剑盾icon

一种很简单的做法,就是给这些物体加上相应的icon模型,位置就和本物体重合,然后将icon模型设置为showInMiniMap,然后在主摄像机里剔除,让他们不会出现在视野里。然后给本来模型,加上hideInMiniMap图层,这样他们就不会出现在小地图了。

如此一来就实现了游戏视图里看到的是模型,而小地图里看到的是icon了。

二、进阶功能

给小地图加个圆框

让小地图和主角一起转动

transform.rotation = Quaternion.Euler(
    new Vector3(
        transform.rotation.eulerAngles.x,
        playerTransform.rotation.eulerAngles.y,
        transform.rotation.eulerAngles.z
    )
);

加上指南针

有些人,看到小地图,就想到圆;看到圆,就想起转动;看到转动,就想起指南针。 —— 鲁迅

没错,接下来我们就做指南针。

让指南针更逼真

现实中的指南针并不会一瞬间指向南的,而是有个慢慢晃动校准的过程,我们也可以做出这样的效果来!

compass.rotation = Quaternion.Lerp (
    compass.rotation,
    Quaternion.Euler (0, 0, playerTransform.rotation.eulerAngles.y+compassOrientationOffset),
    Time.deltaTime * compassRotationSpeed
);

Quaternion.Lerp 是个非常棒的函数, 处理旋转问题呱呱叫!比如说,120度转到-120度,我们无需自己判断是顺时针转动240度,还是逆时针转动120度,这个函数会自动帮您选择最小的度数(120度)转过去。

三、完善功能

为啥是先讲进阶,后讲完善呢?

处理小地图灯光

如果你的游戏世界里存在白天黑夜循环,比如dota2,你又不希望你的小地图黑夜比白天黑很多,顶多视野变得狭隘点。那么就需要给小地图设置另一套灯光渲染。

void OnPreCull (){
    foreach(Light l in minimapLightsNotVisible)
        l.enabled = false;
    foreach(Light l in minimapLightsNoShadows)
        l.shadows = LightShadows.None;
    foreach(Light l in minimapLightsVisible)
        l.enabled = true;
}
void OnPostRender(){
    foreach(Light l in minimapLightsNotVisible)
        l.enabled = true;
    foreach(Light l in minimapLightsNoShadows)
        l.shadows = LightShadows.Soft;
    foreach(Light l in minimapLightsVisible)
        l.enabled = false;
}

处理在屋子里情况

这里应该要分好几种情况,先说两种:

  • 低矮的屋子
  • 高楼

首先,我们进了矮屋子咋办,因为小地图是头顶的摄像机渲染的,所以摄像机会被屋顶挡住。我在小地图里只能看到一个屋顶。这个根据业务需要,解决方法如下:

  • 你可以选择进入某个屋子后,就不渲染这个屋子的屋顶了(需要在代码中做相应的控制),这貌似是很多生存类游戏的解决方案。
  • 也可以选择就是要显示屋顶,都进了屋子里,这个屋子就是个地标,还要啥小地图?

我们这里先提供第一种解决方案的实现。

然后我进了一个高楼咋办?如果我停在1楼,因为摄像机高度是有限的,它很可能停留在3楼或者4楼,那就很诡异了,我在1楼某个屋子走来走去,摄像机却显示了3楼空无一人的场景。这显然是无法接受的。

进入地下城

下面就是个特殊例子了,进入地下城或者蜿蜒曲折的山洞咋办?

众所周知,地下城都是带“盖子”的,天生带屋顶,如果你还是把摄像机放在天空,就有点像进入高楼那种情况了,诡异。而且地下城里高高低低,上上下下,摄像机卡在隔壁房间,甚至卡在你根本没设计的墙外世界,看到外面诡异的天空盒子,这就很像某部科幻电影里的场景了...这是完全无法接受的!

怎么办呢?碰撞检测吧!从摄像机发射一根射线到人物,如果中间碰撞了设定为墙壁图层的物体,就是穿墙了,这时候就把摄像机前移到碰撞点前面一些的位置,这样就不会有问题了。

下面我们开始实现。

结语

其实小地图上可以玩的花样肯定还有很多,这些就等各位大佬慢慢挖掘,自己实现啦。也欢迎大家不吝分享自己的经验,一起进步~

posted @ 2021-08-30 09:56  亚楠老猎人  阅读(1618)  评论(0编辑  收藏  举报