只要你不是山顶洞人
过去几周
你身边肯定到处都是动物之森
这个视频将告诉你
如何在unity里做出动森的世界弯曲效果
但我们不会止步于此
我们也会探索如何更进一步
信我，真的超级简单
世界弯曲效果可以让玩家看到地平线和天际线
保证地面和天空同时都能够被看到
其实现方式被任天堂称之为“滚筒”效果
玩家在地表上行走时
地形好像在玩家脚下弯曲滚动
这个效果有个很有意思的源头
动森设计师江口胜也曾跟IGN表示
对于任天堂DS游戏机
我们用这种滚筒效果的原因是 你在上方的屏幕里看到的是天空， 因为天空在上面， 用这种效果比用水平滚动摄像机更合适
运用这种效果在上方的屏幕显示天空
会比水平滚动摄像机更好
话不多说，让我们开始吧
我先创建了一个有趣的场景
有一个玩家可以控制的船
关于这个场景，有一点需要注意的是
该效果需要面数足够的模型
如果你的模型面数太低
可能会影响效果
如果你想要获得更多关于场景的灵感
动森并不是唯一一款使用该效果的游戏
《戴斯班克》、《地铁冲浪》等游戏也有运用该效果
我做了一个叫世界弯曲的Shader Graph
它有两个属性，一个纹理和一个向量1
向量1的数值应该很小
所以我把滑条的值设为.005到.1
材质的话我只用了albedo纹理
但你想加什么贴图都可以
首先，我们要计算顶点到摄像机的距离
我们只需要Y轴上的距离，所以我们把它拆出来
为达到弯曲的效果
我们把曲率乘以距离的幂*
现在我们可以把偏移后的Y轴位置加到顶点的世界位置了
由于顶点shader需要一个物体空间位置
我们把这个位置从世界空间转换到物体空间
现在我们只需
将新位置与主节点的顶点位置连接起来
基本的shader graph已经做好了
来看看实际效果吧
世界弯曲效果有一个好处是
我们在一个时间只需要展示世界的一个部分
而我们的表面积又并不受限于球体或者圆柱体的表面积
所以我们可以制作出无限大的世界
现在基础结构已经打好了
我们可以继续制作镜头缩放，修些小问题
不过在此之前
让我们加一些渲染效果，让场景更好看吧
我在Window>Rendering>Lighting Settings里加了一些雾
在这个窗口中，我勾选了雾
给我的场景设置了合适的距离
我还添加了后效
就一点点晕影和景深
接下来，我们来试试动森的镜头缩放吧
每当对话开始的时候
摄像机就会改变两个参数
第一个明显就是距离，第二个则是角度
我给工程添加了Cinemachine插件，做了两个摄像机
主摄像机角度设置为50，距离为14
而缩放摄像机的角度设置为30，距离为10
我写了个Cinemachine虚拟摄像机的缩放脚本
脚本运行时会禁用掉摄像机
Cinemachine虚拟摄像机 先禁用摄像机 仅由玩家启用/停用
只会在玩家进入或退出触发时
启用或者停用虚拟摄像机
在这个桥的物件上，我做了个触发碰撞盒
挂上脚本和缩放摄像机
现在当船经过桥底下时
就有了镜头放大的效果
如果你想了解更多关于Cinemachine和镜头缩放的内容
可以看我相关的视频
你可能注意到了，在世界旋转时
远处背景的物体会突兀地消失，而不是一起转下去
这是由于摄像机视锥体裁剪造成的
摄像机视锥体是指玩家可以看到的场景区域
Unity的渲染是不管视锥体外的物体的
在这幅图里我们可以看到
视锥体里被标高亮的树是被渲染了
而我们的shader是在GPU上的
会在渲染前修改物体的位置
CPU是不知道GPU上做出的修改的
如果我们选择一个物体进行移动
你可以看到选择外框线和物体的渲染并不同步
我们的shader弯曲了世界后
就会把更多物体放到视野里
Unity渲染的剔除步骤是在CPU上进行的
就会无视掉视野中不在视锥体里的物体
图片中展示了带shader和不带shader的两种树
被标高亮的视锥体内的树是有被渲染的
蓝色的是被shader修改过的树
可以看到视锥体里有些蓝色的树是没有被渲染的
我做了个弯曲管理脚本
我从渲染管线管理器里注册摄像机渲染事件
摄像机渲染时
我们会基于其位置提供修改后的视锥体
我们的解决方案很简单，用普通视锥体渲染
但当Unity剔除物体时，我们就使用修改后的视锥体
我们会做一个视野更大的斜方视锥体
可以看到位于视锥体内部的蓝色树一直是被渲染的
因此，在视野内的树就能够被渲染
剔除的问题解决了
但还有一个问题要解决
现在我们已经实现了想要的效果和感觉
但修改场景的体验并不是很舒服
我在shader graph里我加了个全局多重编译布尔keyword
把它的reference命名为Enable_Bending（启用弯曲）
我修改了shader，只有keyword启用时才会有效果
我给弯曲管理脚本加了一个ExecuteAlways（一直执行）的属性
脚本Awake以后，根据是否在play模式下
决定启用还是禁用关键词
编辑器在没有play时场景是正常显示的
在shader里，我在深度弯曲的基础上加了水平弯曲
在视觉上就会呈现出球形而非圆木形的效果
现在我们移动的时候，世界在两个轴上都会弯曲
就好像我们在星球的边边上
说到星球
这个效果有三个参数可以调节
来实现不同的效果和感觉
弯曲量，摄像机旋转度和摄像机位置
把旋转度改成90度
再移远一点看看会有什么变化
现在我们可以在这个星球上航行了
调整弯曲量会改变星球的大小
想再进一步吗？
我所讲的这些都只是最基础的概念
这两个超棒的案例也运用了相同的原理
工程文件可以在描述里下载（已附在文中）