引言:去年,独立游戏《笼中窥梦》独特的美术表现令无数玩家赞叹。游戏利用「视错觉」来设计谜题关卡,创造了一个奇妙的立方体世界。本次,「Cocos Star Writer」Nowpaper 将在 v3.5 中实现同款视错效果,源码和视频教程见文末

「视错觉」解密游戏《笼中窥梦》

《笼中窥梦》有很多值得考究的技术细节点,那么今天,我们将在 Cocos Creator 3.5 中使用可渲染纹理和自定义着色器实现一下这个游戏的方盒视错功能,一窥其技术实现思路。

Demo 最终效果

这一次的技术实现灵感来自于我正在制作的另外一个技术视频,那是探讨如何在 v3.x 中实现瞄准镜和额外屏幕技术(PS.这个方案很快也会分享给大家)。偶然发现其中的部分,只要结合之前的传送门技术实现方法,就能做出《笼中窥梦》的方盒视错,于是率先完成了这个方案,第一时间分享给大家。

实现瞄准镜和额外屏幕技术

场景准备,实现分析

《笼中窥梦》中的盒子,各个面展示了完全不同的场景,玩家通过旋转摄像机找到合适的位置,组合达成过关条件。因此我们需要解决的是:如何让盒子的各个面显示不同的画面。

正常来说,我们将使用5个摄像机,渲染不同的画面到方盒的5个面上,这里使用 RenderToTexture 可以很容易地完成。我准备了一些素材搭建了几个不同的场景,需要注意的是,需要注意的是,这里将场景按节点分割,方便管理。

首先搭建一个基础场景,中间摆放一个盒子,并且建立对应各方向的面片。但如果五个表面都制作,那么场景搭建将会异常复杂,为了降低复杂度,我们先做出两个表面,对应的也得做出来2个场景用来当谜题。

这些场景搭建并不复杂,但是如果真的要实现完整的关卡,这就得需要精细设计了。本文主要探讨技术实现,就不做那么细致了。

在项目设置中,新增6个 Layer 用来标记渲染分组,因为对应的摄像机,只需要渲染指定的渲染层即可,不用全部都渲染出来。

现在为它们每个组的根节点设置对应的 Layer,以方便将来摄像机的设置。将基本场景的根节点设置成为 Base,而其他的两个场景根节点分别设置为 Layer 1 和2。如此一来准备工作就完成了。

摄像机的控制代码

接着我们需要先实现一个摄像机的渲染控制代码,让摄像机围绕着一个物体进行旋转。代码相对来说比较简单,通过监听 TouchMove 事件处理旋转,具体的请参看论坛中一些大佬的分享。

import { _decorator, Component, Node,  input, Input, EventTouch, Vec3, v3, Quat, math, quat } from 'cc';const { ccclass, property } = _decorator;@ccclass('CameraControl')export class CameraControl extends Component {@property(Node)target: Node = null;public yMinLimit = -90;//相机向下最大角度public yMaxLimit = 0;//相机向上最大角度private targetX = 0;private targetY = 0;private xSpeed = 25;private ySpeed = 12;private disance: Vec3 = v3();start() {let angles = this.node.eulerAngles;this.targetX = angles.y;this.targetY = angles.x;input.on(Input.EventType.TOUCH_MOVE, this.onTouchMove, this);Vec3.subtract(this.disance, this.node.worldPosition, this.target.worldPosition);this.disance = v3(0,0,this.disance.length());}private onTouchMove(touch: EventTouch) {this.targetX -= touch.getDeltaX() * this.xSpeed * 0.02;this.targetY -= touch.getDeltaY() * this.ySpeed * 0.02;this.targetY = this.ClampAngle(this.targetY, this.yMinLimit, this.yMaxLimit);}private _quat = quat();private _vec3 = v3();update (deltaTime: number) {Quat.fromEuler(this._quat, this.targetY, this.targetX, 0);Vec3.transformQuat(this._vec3, this.disance, this._quat);Vec3.add(this._vec3, this.target.worldPosition, this._vec3);this.node.worldPosition = this._vec3.clone();this.node.worldRotation = this._quat.clone();}ClampAngle(angle, min, max) {if (angle < -360) angle += 360;if (angle > 360) angle -= 360;return math.clamp(angle, min, max);}}

回到编辑器中,为主摄像机添加脚本,并且指定目标,测试旋转效果。

新建一个摄像机,命名为 Camera 1。然后复制主摄像机节点参数,粘贴给新建的摄像机,调整到合适的位置,用来拍摄第一个场景。设置这个摄像机的可见性掩码,只勾选 Layer 1 这个 Layer 层。

然后再实现一个摄像机同步的代码,用来处理面摄像机和主摄像机的同步。实现同步只需要在开始的时候,计算两个摄像机的偏移值,同步位置和旋转时候修正即可。

import { _decorator, Component, Node, Vec3, v3 } from 'cc';const { ccclass, property } = _decorator;// 同步摄像机脚本,事实上如果监听主摄像机坐标、旋转差值会更加合理@ccclass('SyncCamera')export class SyncCamera extends Component {@property(Node)mainCamera: Node = null;offset: Vec3 = v3();_vec3 = v3();start() {Vec3.subtract(this.offset, this.node.position, this.mainCamera.position);}update(deltaTime: number) {Vec3.add(this._vec3,this.mainCamera.position,this.offset);this.node.position = this._vec3.clone();this.node.rotation = this.mainCamera.rotation;}}

先实现一个面

现在我们先实现一个面看看效果。

新建一个材质,选择着色器为内置 builtin-unlit,勾选 Use Texture,新建一个可渲染纹理,设置宽高为 512x512,把刚刚新建的可渲染纹理,拖到上面完成引用。

在场景中选择 surface 1 的面片,将它材质替换,就可以看到摄像机画面,渲染到表面1上,现在我们运行一下看看效果,由于有摄像机同步脚本,当主摄像机调整的时候辅摄像机也会跟着变动。

接着用同样的方式建立第二个表面的渲染画面。

但是很快我们会发现有个不对劲的地方:这个画面看起来非常的平,根本就不像是透视过去的画面。这是因为现在表面是直接将拍摄到的渲染画面显示出来,这样肯定是没有透视效果的。

这个时候就需要一些特殊的处理。在我之前有关传送门的分享中,这个问题也没有解决得很完美,后来在 Cocos 的 Panda 大佬的帮助下,通过修改着色器 Shader 达成了完美的传送门效果,本方案就将用到这个着色器文件,大家也可以到 Cocos Store 中免费下载。

「传送门实现」源码免费下载:

https://store.cocos.com/app/detail/3275

也可以参考 youtube 大佬 Sebastian Lague 的有关视频,他对透视计算 Shader 和原理的讲解非常详细,本文中的实现只是他的简化版本。

https://www.youtube.com/watch?v=cWpFZbjtSQg

核心代码如下:

float flip = cc_cameraPos.w == 0.0 ? -1.0 : 1.0;v_screenPos = pos * 0.5;v_screenPos.xy = vec2(v_screenPos.x, v_screenPos.y * flip) + v_screenPos.w;v_screenPos.zw = pos.zw;

将修改过后的着色器添加到工程,然后选择 surface 的材质,修改 Effect 点击保存,运行就可以看到效果,现在透视基本上 OK 了。

不过好像还有一些小细节可以调整,比如画质发生了变化、显示的内容更近了,这个需要我们自行对摄像机进行调整。但是为了更好的设计关卡,两个摄像机的有关参数应该保持一致,否则可能会出现奇怪的视觉错误。

视错谜题

经过参数调整,效果已经非常不错了,那么我们也设计一个简单的谜题到其中。

这里有一幅画,放进第一个场景中,然后再往第二个场景中添加一个,此时需要一些空间视觉感,来调整对应的位置和角度。这里可能需要我们反复对比摄像机呈现的画面和最终运行结果,才能调出满意的效果。

运行一下看看效果。一般情况下,我们透过两个表面看到的画并不能完全重合,经过拖动旋转可以让其完全重合。

结语

好了,剩下的就是关卡设计的问题了,您可以利用本篇中的技巧,使用 Cocos Creator 完成一个自己的《笼中窥梦》游戏。今天这个技术实现本质上是将 RenderToTexture 给用活了,只要稍微调整一下,你也能做出令人叹为观止的创意。

我一直认为,技术工具都是为创意服务,人类的创意总是没有尽头,如何实现心中所想,除了对它的热爱,工具的熟练度和技术的沉淀,才是创意发挥的基础。

资源链接

  • 点击文末【阅读原文】前往 Cocos Store 下载本项目源码(含三个基础场景资源、三个面的实现场景,可以很方便地进行扩展):

https://store.cocos.com/app/detail/3791

  • 视频教程(UP 主:Nowpaper)

https://www.bilibili.com/video/BV1D3411G7jy

  • 论坛讨论帖:

https://forum.cocos.org/t/topic/135819

今天的文章就到这里了,我是 Nowpaper,一个混迹游戏行业的老爸,如果您喜欢我的分享,不妨多多点赞留言,也欢迎关注我的 B 站,您的支持是我更新的动力,下次再见!

Nowpaper 往期分享

《守望先锋》同级的枪弹射击体验

《时空幻境》时间倒放玩法

《饥荒》同款视觉表现

用 RenderTexture 实现小地图与传送门

卧槽,3D错觉!这脑洞简直了...相关推荐

  1. 华为mate10手机听筒测试软件,华为mate 10功能说:这几个设置,让你通话体验直线上升,简直了!...

    原标题:华为mate 10功能说:这几个设置,让你通话体验直线上升,简直了! 手机从发明以来到如今,一直有那么几个功能是最核心的,通话功能不用多说吧,虽然现在有了各种社交软件的视频.语音等等,但是在很 ...

  2. 简直了!10年难得一见的Tuxedo服务异常

    "tuxedo服务在电信金融系统中广泛存在,但在马爸爸互联网飓风的席娟之下,曾经的辉煌已然不在.但作为重量级遗留资产,仍然在困扰着运维的同志们.莫名的异常,经常被搞得彻夜难眠!" ...

  3. CVPR 2021 | 这3D人脸追踪的稳定性、贴合度、真实程度,简直了

    点击上方"3D视觉工坊",选择"星标" 干货第一时间送达 Title 本文作者来自 Facebook 和美国罗彻斯特大学,作者提出了一个基于深度学习的光照模型 ...

  4. 教你黑掉一台不联网的电脑!网友:我擦嘞!这方法简直了……

    一直以来,拿到一台电脑上的密钥,方法无非有以下三种: 1.直接拿到这台电脑,然后输入木马病毒进行盗取.(此种略微LowB的方法风险在于:如果被电脑主人"捉奸在床",愤而报警,则需要 ...

  5. 知乎高赞:这个开挂神器简直了!

    全世界只有3.14 % 的人关注了 爆炸吧知识 对于工作学习中常要用到PPT的人来说,每当谈起PPT,是否都会出现以下印象: [买模板]→[改PPT]→[粘贴复制]→[应付领导] [操作繁琐]→[体力 ...

  6. redis 清空缓存_「镜头回放」简直了!spring中清除redis缓存导致应用挂死

    异常场景 springWeb应用一直运行正常,同事最近反应,每次版本更新完毕,刷新缓存,就会导致应用挂死.只有重启redis应用才恢复正常. 项目概况 springWeb项目,常用配置表做了redis ...

  7. 那些年踩过的Java异常,简直了!

    1.NullPointerException 空指针异常,操作一个 null 对象的方法或属性时会抛出这个异常.具体看这篇文章:Java 避免空指针的 5 个案例. 2.OutOfMemoryErro ...

  8. 全系统翻译 macOS Monterey这个新功能简直了

    随着10月26日macOS Monterey正式版的发布,Mac「全系统翻译」功能终于来了! 「全系统翻译」最早在iOS 15上与我们见面,考虑到大家的科研/学习活动主要在电脑上,那么Mac「全系统翻 ...

  9. vscode同时打开多个文档方法,简直了

    @TOCvscode同时打开多个文档方法,感觉智商受到伤害 使用vscode写页面工程发现无法同时打开多个文档进行比对,感觉很难解决,查阅发现实际简单的受不了. ##就这样了

最新文章

  1. 三星手机Android9和10的区别,三星开始在Galaxy Note 9上测试Android 10
  2. 嵌入式_makefile简单语法介绍
  3. 理解至上:二叉堆与优先队列详细用法
  4. 在TensorFlow中使用pipeline加载数据
  5. Spring 声明式事务应该怎么学?
  6. easy connect电脑版_北师大版小学英语六年级上册Unit4课文听力+翻译+单词录音跟读+高清课本(一起点)...
  7. [论文笔记]ALBERT: A LITE BERT FOR SELF-SUPERVISED LEARNING OF LANGUAGE REPRESENTATIONS
  8. 观点对立,无关虚拟现实技术
  9. Flutter高性能,线程安全,App开发的未来
  10. 骑士资本高频交易系统事故案例分析
  11. 2020-10-28网络安全之网络安全产品
  12. unity编译器安装路径_1.安装Unity
  13. 2022-2028年全球与中国手持式按摩器行业市场深度调研及投资预测分析
  14. TP-LINK配置无线上网短信Wifi认证方式
  15. 使用Clonezilla复制硬盘
  16. 利用CSS制作一个梦幻西游小动画
  17. 表格内容如何合并在一起
  18. 电脑如何录屏?分享4个屏幕录制的好方法,建议收藏
  19. 教你怎样用安全网关消灭蠕虫病毒(转)
  20. Python 转换金额数字大写为数字小写

热门文章

  1. 其他笔记-Pycharm必备插件推荐
  2. C语言实现【小游戏——反弹球消砖块】
  3. matplotlib工具栏源码探析四(自定义工具项图标)
  4. 一文实现Mac 上简单定时提醒小脚本
  5. idea批量修改变量快捷键mac_IDEA 快捷使用指南
  6. 微信小程序获取用户收货地址列表wx.chooseAddress
  7. 八位一体共阴极数码管显示电子时钟+闹铃+温度检测
  8. 我的世界服务器反反作弊最新版,【服务器插件】【完全的反作弊】
  9. JDK10新特性讲解
  10. node.js毕业设计微信签到小程序(源码+程序+LW+部署)