• 用Unity重现《空洞骑士》的苦痛之路(2)——地图篇


    前言:

    大家好。虫虫大冒险(?)新的一期又双叒叕来了。

    本期文章主要讲解《空洞骑士中》的地图搭建相关的内容,并会写一个简单的相机脚本。除此之外,还会涉及到如何制作背景、产生异于玩家移动的动态效果。好了,闲话不多说,直接开始。

    地图模板

    工欲善其事,必先利其器。在开始地图搭建之前,我们先制作好游戏需要的地图模板,这样在后续的地图搭建环节中可省去大量的时间与精力。

    如何搭建地图模板就不多说了,通过图片资源对比实际游戏画面,然后再组合即可。大约有以下几种主要的模板:

    值得注意的是,地面与墙壁的柱子形状的物体的纹理重复使用,是需要在精灵图片属性中编辑九宫格,并在SpriteRender-DrawMode中设置为Tiled,并调整参数才能够有正确的纹理重复的效果。如下:

    这块技巧在使用Unity制作UI时会频繁用到,无论什么游戏。没接触过的童鞋可以留心一下。

    由于机关陷阱物体是可以移动的,因而我们还需要写一个简单的机关移动脚本,来控制陷阱的移动。主要逻辑是:先获取陷阱能够到达的最上方点与最下方点,然后让陷阱在其中来回移动。其实现代码如下:

    public enum TrapMoveDir

    {

        None,

        Down,

        Up,

    }

    public float moveSpeed;//移动速度

    public bool isMove=true;//是否进行移动

    public Transform startTrans;//开始的点

    public Transform endTrans;//结束的点

    public Transform trapObj;//陷阱物体

    TrapMoveDir moveDir;//移动方向枚举

    public void TrapMove()

    {

        if (moveDir == TrapMoveDir.Down)

        {

            trapObj.transform.position += transform.up* moveSpeed * Time.deltaTime*-1;//朝下移动

            float distance = Vector3.Distance(trapObj.transform.position, startTrans.position);

            if (distance<0.5f)//如果现在距离最下面的点小于0.5f,重新设置移动方向

            {

                moveDir = TrapMoveDir.Up;

            }

        }

        else if (moveDir == TrapMoveDir.Up)

        {

            trapObj.transform.position += transform.up * moveSpeed * Time.deltaTime;

            float distance = Vector3.Distance(trapObj.transform.position, endTrans.position);

            if (distance < 0.5f)

            {

                moveDir = TrapMoveDir.Down;

            }

        }

    }

    地图分层

    为了实现原版游戏中景深的效果,我们需要正确的利用SpriteRender中提供的层级功能(Sorting Layer 或者使用Order in Layer),以制作出想要的效果。其中主要的层级分布大致如下:(PS:原版游戏中的层级远远超出下面列举的这几种,这里只是简化版) 

     优先级从上到下排列,最上面的的优先级最高。其中第一层半透明白色遮罩的主要效果,是用于模糊背景物体,产生人物与场景深度不一致的效果。

    地图搭建

    在开始搭建地图之前,推荐自己先画一个地图草图,然后按照草图进行搭建。搭建的时候可能不会跟草图一摸一样,但总是比毫无目标的乱搭一气好得多。如果你是想做到完全跟原版一样,那么这一步你就可以跳过了。类似如下:

    接下来就是按照草图,选择合适的地图模板和对应的图片搭建地图了。其中为了实现荆棘地形散乱生长的感觉,没有制作对应地形的模板,而是根据周围环境手动调整荆棘图片的旋转缩放参数来实现相应的效果。


    而地图中窗户的效果就需要花点心思来实现了。首先需要设置好需要通过窗户才能够看见的物体的层级,然后还需要添加比窗口物体层级小的黑色遮罩,来遮挡住其余不需要被查看的部分。

    简易相机

    到了这一步,地图、玩家都准备好了。只需要一个相机游戏就可以试玩了。

    现在我们来写一个简单的相机控制脚本。由于我们是2D游戏,可以忽略Z轴上的位移来进行相机的移动控制,于是我们的相机的控制原理如下:

    GIF

    其实现代码如下:

        public Transform player;   //玩家

        Camera playerCamera;        //主相机

        Vector2 boxSize;            //视野范围

        public bool cameraMove;

        public void FollowPlayer()

        {

            Vector3 targetPos = new Vector3(player.position.x, player.position.y, transform.position.z);

            transform.position = Vector3.Lerp(transform.position, targetPos, 0.08f);//插值进行移动

            float distance = Vector3.Distance(targetPos,transform.position);

            if (distance<0.5f)//距离小于0.5f时 停止移动

            {

                cameraMove = false;

            }

        }

        public void CheckBoundary()

        {

            float leftDistance = 0; //左右距离

            if (player.position.x < transform.position.x) //在左边

            {

                leftDistance = transform.position.x - player.position.x;

            }

            else

            {

                leftDistance = player.position.x - transform.position.x;

            }

            if (leftDistance > boxSize.x * 0.5f)//如果左右距离大于设置好的矩形宽度的一半

            {

                cameraMove = true;//相机开始移动

            }

            float uDDistance = 0;   //上下距离

            if (player.position.y < transform.position.y)

            {

                uDDistance = transform.position.y - player.position.y;

            }

            else

            {

                uDDistance = player.position.y - transform.position.y;

            }

            if (uDDistance > boxSize.y * 0.5f)

            {

                cameraMove = true;

            }

        }

    背景移动

    在现实世界中,人移动时肉眼看远方,远处的物体总是移动的比自己慢。而我们就是需要模拟这种特性,来完善我们的景深效果。

    实现原理:游戏一开始获取玩家的位置并保存,然后每一帧计算出玩家已经移动的距离,然后使用计算出来的移动位移,来计算出背景此时的坐标。代码如下:

        public Transform player;

        Vector3 backStartPoint;     //初始背景的位置

        Vector3 playeStartPoint;    //初始玩家的位置

        public void BackMoveFunc()

        {

            float tempX = player.position.x - playeStartPoint.x;

            float tempY = player.position.y - playeStartPoint.y;    //计算X,Y两轴的历史位移

            float xVaule = tempX * 0.08f;

            float yVaule = tempY * 0.06f;//计算出背景的X,Y轴位移

            transform.position = new Vector3(backStartPoint.x + xVaule, backStartPoint.y + yVaule, 0);

        }

    这里只让一层的背景进行移动,如果想要更好的效果,可以多加几层,使移动的速度不同,这样的效果将会更加逼真。

    工程下载链接:https://pan.baidu.com/share/init?surl=DD2_yJh-rulqpNgIDAuZjA
    提取码: 7gw1 

  • 相关阅读:
    FedAvg算法+LSTM模型+ Shakespeare数据集——字符预测任务
    提升树与GBDT的详细算法过程(建议收藏版)
    【软考-中级】系统集成项目管理工程师-质量管理历年案例
    微信小程序备案内容常见问题汇总
    【玩转Redhat Linux 8.0系列 | 从命令行管理文件(二)】
    热门项目!知识付费小程序源码系统 带完整的安装代码包以及安装部署教程
    大语言模型(LLM)Token 概念
    盘点Spring/Boot的那些常用扩展点
    Windows OpenGL 图像对比度调节
    阿里、美团、拼多多、网易大厂面试之Redis+多线程+JVM+微服务...
  • 原文地址:https://blog.csdn.net/m0_69824302/article/details/127830885