摄像机视角的有趣玩法,实现《饥荒》同款视觉表现,一毛一样

说明

本文为B站视频的配套文章,如果您觉得不错,请一定关注三联一波!

简介

大家好,我是Nowpaper
八方旅人和饥荒的游戏视觉呈现非常有趣,你能清楚的知道它是2D素材,却呈现出一种3D世界的感觉,这种2D和3D混合的游戏,在游戏历史中,很早就有出现,比如轩辕伏魔录、空之轨迹、仙境传说等等



其实实现原理并不复杂,就是在游戏世界中,实现2D素材3D化的一种制作手段,当然了反过来也可以,因此只要游戏引擎支持2D和3D的渲染,就能实现同样的立体效果

目前,在CocosCreator3中并不能非常容易的实现这个效果,也是经过一番折腾才找到方法,希望能够抛砖引玉,发掘更有趣的玩法
实现效果如下:
动画

Store地址

https://store.cocos.com/app/detail/3373
如果不存在请参看本贴的后续评论和留言

实现思路

按照正常的思考套路,应该将素材导入到工程,然后使用2D精灵,给3D化,但是这个方式并不可行,来通过这个例子来证明,放一个图片进入Creator工程,然后新建Canvas,将图片拖进画布,我们在3D空间中,可以看到这个精灵,按说这个精灵,应该可以在3D空间中渲染,但是很遗憾,它并不能出现在3D空间中,只能在Canvas里被渲染,来尝试一下就知道了,直接在画布上,进行3D的X轴旋转,你会发现图像的模型已经变换了,但是图像的画面还是2D的

因此这个方案并不可行,那么,只能用其他的方式来解决,最繁琐的一个方式,就是将2D素材全部以纹理的形式,制作成各种材质,然后贴到一个方片网格上,就如我现在实现的这样

image

虽然可以在3D空间里展示了,但是你会发现,这个太麻烦,需要对所有的素材进行材质创建,而且适配和制作动画也比较麻烦,所以,我们将采用Creator支持的2D渲染的资产类型,那就是Spine、龙骨和Tiledmap解决,因为在我的各种实验中,只有这3种类型的资产,在画布上可以进行3D空间各个轴的变换,图像也会跟着变化,而不是像Sprite图像一样,不会有3D空间变化

image

既然如此,那么我们就用龙骨来实现2D的人物动画和物件的素材渲染,我用龙骨软件,经过一番操作,实现了一个小人的行走动画,一个树木的资产,关于地面,我准备了一个地块拼接图,直接放置到项目资产中了


创建项目

(高手请直接跳过,到 视觉实现)

现在在新建项目当中,新建一个场景,建立一个Canvas,拖一个地面的精灵,利用精灵的平铺特性,生成一个你觉得足够大的地图,当然了这里也可以使用tiledmap来绘制地面,这里我就直接一个节点就搞定了


在右上方打开约束控制设定,把约束设定成为你的地块格子宽高,我这个地块是80,这个功能是Creator3.3版本新加入,当时我盘点的时候就说这个改进非常有用,这不马上就用上了,因为有了坐标控制约束,在地图上摆放各种物件就显得非常舒服

image

等设置完成后,我们在地图上加入一个节点层,将它命名为环境吧,然后在这个节点上种树,种树的操作就看个人的喜好了,放置的树是咱们用龙骨实现的那个,其实Spine也行,种完树之后,把小人放到环境节点里

image

请先实现人物的行走,这个脚本相对来说比较简单,只是需要自己实现一个按键的监听,处理x、y输入,先实现wasd按键的处理,在Update里面实现人物的移动的逻辑,您可以使用您熟悉脚本实现

我的项目中的行走脚本,是 PlayerController.ts

// 代码请移步 Store 下载
// https://store.cocos.com/app/detail/3373
// 或参看后续帖

视觉实现


现在重头戏来了,让我们改变一下摄像机,让世界变成一个3D的环境,点击一下右上角的视角切换,变成3D模式,你会看到,其实Canvas就是一个面片网格,它本身就在3D空间当中,现在新建一个摄像机,用Main摄像机修改过去也可以,先把Canvas的摄像机给关闭掉,以后有UI了再说,将摄像机X轴旋转45度,稍微调整一下对准主角,我们可以看到摄像机里呈现的是3D样式

这个时候可以试试,修改一下树和主角,你会看到通过修改X轴的数值,能够让它们在2D画面中“立”起来,而这就是实现饥荒视角,同样效果的秘诀,在这个阶段,其实就可以直接在2D画面中摆放3D环境了,但是物件实在太多,我就简单写一个脚本EnvManager.ts

// 代码请移步 Store 下载
// https://store.cocos.com/app/detail/3373
// 或参看后续帖

在这个脚本中,让所有的环境子物体,全部根据摄像机的朝向旋转,顺便完成一下环境物体的排序,根据画家算法,让Y轴排序节点,实现近处遮挡远处的效果,将这个脚本添加到环境物体节点组上,并添加摄像机的引用,然后运行,你会看到所有的环境组中的子物体,全部都“立”了起来,

image

当然了这么看,还没有什么明显的效果,因为摄像机没动

下面实现一下摄像机跟随,和视角的变换,跟随是根据主角的位置进行位移,由于摄像机的已经在3D世界中,设置的坐标不好确定,这里我们采用一种控制点的做法,就是在主角的同样位置上,有一个控制节点一直同步主角的坐标,而摄像机则挂在这个节点上,这个节点移动,摄像机也跟着移动了,而实现世界旋转,只需要对它进行旋转即可,因为摄像机一直处于它的子坐标系中

脚本是:CameraController.ts

// 代码请移步 Store 下载
// https://store.cocos.com/app/detail/3373
// 或参看后续帖

在这个组件脚本里面,需要指定一个目标,在开始的时候计算出偏移量,然后在Update里面,不停的设置它的坐标就可以了

视角旋转

在饥荒游戏中,视角可以呈现一定角度的旋转,我们就实现一个按Q和E来,实现左右旋转摄像机的脚本

CameraController.ts脚本监听KeyDown事件,实现一个旋转方法,当按下QE的时候调用这个方法,为了让旋转执行中不会被再次调用,我们用一个变量来锁定判断,然后用Tween来处理这个旋转,先取出来自身的角度,然后做一下to的缓动行为,成功之后去掉锁定变量,OK!在按键事件中进行调用,分别是-45和+45,具体代码,在CameraController.ts

由于摄像机的的旋转跟随了控制点,所以在环境物体管理脚本中,也得需要作一下修改,让角度变更跟着控制点刷新
EnvManager.ts

// 代码请移步 Store 下载
// https://store.cocos.com/app/detail/3373
// 或参看后续帖

保存回到Creator中,将CameraController添加到摄像机的控制点上,运行看看效果吧。

两大缺陷的解决

但是就目前为止,还存在两个问题:

  • 第一是旋转之后移动控制,还是按照之前2D的方向,并没有根据摄像机的旋转作调整,这就很别扭了
  • 第二个问题是,画家算法已经对旋转之后的画面,有了错误支持,你会发现人物的遮挡关系是错误的

关于摄像机相对移动

需要进行一个数学的运算,在主角的脚本的Update里,计算出来的inputX,乘以自身对应的right方向向量,inputY乘以自身的Up方向向量,得出来的标量就是旋转过,和屏幕对应的x和y的输入量了,因为主角跟随着摄像机在旋转,所以对应的方向了也发生了改变,如果你的主角不是这样的,请注意计算方法,否则可能会出错

核心代码:

const right = this.node.right.clone().multiplyScalar(inputx);
const up = this.node.up.clone().multiplyScalar(inputy);
const newInputXY = right.add(up).normalize();

关于2.5D空间的绘制排序

第二问题是视角旋转之后,物体渲染排序不对,这个咱们使用距离计算的方式解决,也就是说距离摄像机越远的越先绘制,这样近处的排在后面,遮挡关系就对,在环境物体管理器脚本 中,我们需要计算一下,物体和摄像机的世界坐标距离,然后在排序中进行计算,得出新的顺序
核心代码

let d1:Vec3 = v3(),d2:Vec3 = v3();
const worldPosition = this.camera.node.worldPosition;
this.node.children.sort((a,b)=>{
    Vec3.subtract(this.d1,a.worldPosition,worldPosition);
    Vec3.subtract(this.d2,b.worldPosition,worldPosition);

    return this.d2.length() - this.d1.length();
})

结束语

至此,饥荒同款视角DEMO已经完成了,如果想更精致的效果,还得需要更多的美术资源支持,甚至shader、后期处理之类的配合,就目前而言,Creator的有趣玩法,还没有完全挖掘出来,期待更多的开发者找出好玩的技术点子

希望本次视频对您有帮助,我是Nowpeper,一个混迹游戏行业的老爸,我们下次再见!

其他

本人喜欢研究各种有趣的玩法,以下是往期制作,可以移步研究

Raycast射线实现3D世界交互,如何实现立体界面UI

用RenderTexture实现Sprite版小地图和炫酷的传送门

好玩的编队代码,魔性队伍排列惊喜不断完全停不下来

手撸三个有关Bundle详细教程,大厅+子游戏模式从入门到进阶

Cocos3D《病毒传播模拟器》游戏版本1 开发日志和总结

案例开发 四图猜词 Part1~4 全集教程

37赞

无敌是多么多么寂寞,mark

非常赞!顶了。

太牛了,效果拔群!

为杨老师打call!!!

杨老师太牛了!!!文章我必须转走!无敌!

全部spine或者db性能和合批不好搞啊

秀秀秀。。。

快学学大佬的操作

厉害了我的哥

用到了 再说

牛蛙牛蛙牛蛙

这个太好玩了

mark下

干锅干锅干锅

狂吃逛吃狂吃

别人只是提供一个方案,性能自己搞就好了啊。

如果有个建筑怎么办了?

大佬牛逼,我有个建议,其实sprite的type设置成九宫格或者平铺模式就可以在3D相机里实现3D旋转了,这样就不用转化成spine了,能避免过多spine无法合批带来的消耗。

求方案效果 :kissing_heart: