【MMORPG开发日志011】UE4制作minimap小地图

【MMORPG开发日志011】UE4制作minimap小地图

写在前面

最近在考虑做一些相对完整且独立的模块,思来想去最终还是决定写一个minimap这种几乎所有游戏都会用到的功能模块。
关于小地图制作的视频版可以看我的B站个人主页:

【老李RPG】21期,UE4小地图简单实现

视频发布之后我觉得讲的还不够清楚,于是决定写一篇文章来补充一下。
其实关于小地图的实现我之前已经写过一篇文章:

RPG游戏开发日志11:小地图实现

只不过那篇文章更像是提供一种思路。
废话不多说,我们赶紧进入正题吧!

实现思路

小地图的实现思路,其实就是通过一个头顶摄像机将画面实时显示在UI上而已。

在UE4中,将摄像机中的图像渲染到某个纹理中的组件叫SceneCapture2D。这个功能也很大程度上依赖于这个组件。

另一方面就是对于细节设计的补充:通常情况下小地图是会旋转的,而在我们这类视角的游戏中,小地图的旋转不依赖于角色而是摄像机。要实现罗盘效果可以在逻辑层或者材质层实现,这里我们选择后者,所以重点就是关于材质的解析。
原理很简单,就是当摄像机转动时候对应调整材质中UV的转动即可。

而小地图正中心的玩家标记,理论上我们可以使用同样的方式,但这里我们换一种实现思路,改为在逻辑层面实现。实现思路就是借助Sprite组件,这个组件主要用于2D游戏中,在minimap中我们可以设置小地图摄像机捕捉Sprite,而游戏主摄像机不捕捉此Sprite即可。对于游戏中的NPC等特殊标记也可以使用此种方式。

材质M_CircularMinimap

创建材质并命名为M_CircularMinimap,

M_CircularMinimap

首先就是对材质本身进行一些设置:

材质设置

将材质的MaterialDomain设置为UserInterface(字面意思就是UI用材质),并且将BlendMode设置为Translucent

之后就是纹理,这里我们需要三部分,都做成参数,为我们之后为mod制作开放接口。这三个纹理图分别代表着:底图、罗盘图和实际map渲染图。

由于这里我们使用的是圆形小地图,因此这里将渲染纹理如下图所示处理一下:

处理渲染纹理

然后将其和我们的底图进行组合:

组合底图

然后如法炮制将罗盘图再进行组合:

组合罗盘图

当然,要实现罗盘纹理的旋转效果,就需要对其UV进行旋转操作:

旋转UV

这里我们将Rotation(float类型)提取出来作为一个参数,方便我们在蓝图中操作。这样关于材质的设置就全部完成了。

Player角色蓝图设置

在设置角色蓝图前,首先是新建一个SceneCapture2D的子类蓝图

SceneCapture2D

并将其作为子Acto添加到Player蓝图中:

添加到Player蓝图中

其实这里也可以直接在Player蓝图中添加SceneCapture2D Component
但之后我们需要在这个Actor中添加一些逻辑,因此我们没有选择组件的方式。
简单讲就是组件密闭性高,不利于拓展,Actor相反。
这里我们和游戏主相机一样,给他添加了一个SpringArm组件,理论上游戏中的摄像机都需要配合摇臂一起使用。这里不多谈了。

正如上文中所说,这里我们给Player添加了一个精灵Sprite组件,如下图所示:

Sprite组件

这个组件要在minimap中渲染出来代表玩家,并时刻同步玩家转向:

玩家的化身

不过这个组件在主相机中可不想被渲染出来,这里我们简单处理,设置精灵组件的OwnerNoSee属性为ture即可。

OwnerNoSee

此外,我们不希望摄像机随着角色转动而变换角度,这会影响minimap中的地图转向,这里我们手动的设置相机摇臂的世界转向值:

设置摇臂的转向不再变化

SceneCapture2D

在Unreal当中,所有需要将相机中内容渲染在材质上的操作都可以用到这个类。这里我们没有做更多扩展操作,只是简单设置了相机需要渲染的对象类型:

筛选渲染对象

更多扩展内容,我们会在升级版的小地图实现中提到。

W_MiniMapBase界面

为了在之后实现各种不同类型的minimap,这里我们抽象出一个UI基类:W_MiniMapBase

在这里做的操作十分简单,首先就是在构造事件中进行初始化,获取上文中提到的SceneCapture并持有:

持有SceneCapture

同时我们动态的创建一个材质的实例,方便我们之后对其中参数进行调整:

创建材质实例

最后我们设置一下材质中用到的渲染纹理:

渲染纹理赋值

然后,在tick事件中,我们获取摄像机的旋转,并改变材质罗盘层UV的旋转变化:

罗盘旋转效果

此外,我们这里实现一个放大和缩小minimap视野范围的事件,供子类调用:


放大缩小事件

而关于视野变化的具体方法,也很简单,只需要改变正交相机的OrthoWidth即可,但值得注意的是,由于我们并没有每帧更新游戏画面,所以在变化后需要手动的渲染画面一次:

OrthoWidth变化

这样Base基类中需要实现的内容就实现完了。

W_MinimapRotating

这个才是我们游戏中实际的效果,首先我们简单的罗列各种UI控件:

UI控件布局

然后我们进行构造事件,这里主要是对父类中使用到的控件变量进行赋值操作:

控件变量赋值

然后在每一帧中更新材质中的Rotation参数:

更新Rotation参数

最后,就是将按钮的点击事件和父类中的扩大、缩小视野范围的事件绑定上。
至此,一个还算说得过去的minimap就完成了。

写在最后

最后只是唠叨一些和本文内容无关的有的没的。

最近这个项目的开发又进入一个纠结期,大家也能看得出来我在过去几个月的开发过程中,很多时候心态是摇摆不定的。对于游戏的核心玩法究竟如何也没有确定下来,更谈不上信心。也正因如此才频繁开发一些与核心无关的,相对通用的模块。

我清楚这是独立游戏开发过程中时常面对的困境。这种没办法(或者说没勇气确定核心玩法)的心态是我目前很难克服的心理障碍。

希望自己能尽快确定游戏的核心玩法,来让这个项目的开发迈出新的一步吧,我也担心再这样拖下去,可能随时有弃坑的风险!

你可能感兴趣的:(【MMORPG开发日志011】UE4制作minimap小地图)