UNITY小白:无需写shader 做拟真瞄准镜
在FPS游戏中打狙时,我们看到镜子通常是这样的:


而有些游戏的狙击镜却与此天差地别:

这时作为小白的我们就不禁疑惑:究竟怎么样才能做出这样狂拽酷炫屌炸天的狙击镜呢?
成品资源(不看教程你可能会理解不了,但教程有点长...)——(度盘链接传统开头https://pan.baidu.com/s/)1GrrFhoULDAiRJ3QaZ6eBwQ
TQ码:wt8c
转入正题:如何做出如此new bee 的狙击镜效果
首先,我们要制作一个镜片的模型:
打开blender(没有的去steam或官网下)
在上方工具栏的 添加 中新建一个圆环网格(顶点数自己设置),在编辑模式下按a全选顶点,再按f连接得到一个圆形平面

翻转法线,不然它在unity显示本应该朝上的一面会不可视,而下方的一面可视,反过来了。

仅仅如此还不够,我们还要给它纠正好UV。编 辑 模 式 下点击上方工具栏的UV,选择块面投影。后面再在 顶端列表 点击 UV Editing,全选UV图

按S键,进入缩放调整模式,再按X键,直接在键盘上打出-1,即可将UV的x轴缩放设置为-1

接着导出FBX模式。

在这之后,打开你的unity,先新建一个空物体 狙击镜(不要随意更改其缩放!若父物体缩放不为1,1,1,其旋转时子物体很可能会变形)。再新建一个圆柱(命名为镜筒)并拖出一个镜片(命名为PPIP)预制体作为其子物体,调整成如图。

新建文件夹PIP,然后新建纹理Black,颜色调黑,贴到镜筒上。
设置缩放使它们与现实狙击镜的尺寸差不多(不用更改父物体的大小),然后记录下此时镜片预制体的的 x y 轴缩放:(4.75,4.75)

在镜片处新建一个摄像机,我名其为PPIPCamera(把 Audio Listener 去掉)
在PIP文件夹新建一个Particles/Standard Unit纹理与一个RenderTexture(分辨率为1536 x 1536)二者都名为 PPIP
将PPIP.RenderTexture分别拖入纹理PPIP的Albedo 与 PPIPCamera的Target Texture。
这时你就会发现:PPIP摄像机所看到的画面被投射到镜片上了。

复制PPIP然后粘贴至狙击镜下,然后把“PPIP”都改成“PIP”。
将PIP往前移一点点

在PIP文件夹新建名为 PIP 的renderTexture(分辨率可以不用这么高,1024*1024)与Particles/Standard Unit纹理各一。
将PIP.RenderTexture分别拖入纹理PIP的Albedo 与 PIPCamera的Target Texture。(类似上文)
接着新增layer名为PIP,将PIP及子物体的Layer都设置成它。
主相机 与 PIPCamera渲染遮罩除PIP外都勾,而PPIPCamera的渲染遮罩只勾选PIP。
接着把PPIPCamera的BackGround选为solid Color,改黑色。

适当调整PPIPCamera的FOV,使PIP镜片 几 乎 能填满PPIP镜片画面

准备工作结束,接下来开始正片!
新建脚本OpticalSight,添加变量

如图,我们现实的瞄准镜是这样的

我们可以将其理解为这样

为了营造出PIP镜片随主相机变化的效果,我们应在update里添加如下代码:

查看效果,NICE!!!

我们如果仔细观察,还会发现狙击镜有虚像效果,即放大的成像就像深水王子,不会随你眼睛距离远近的变化而放大缩小。
为此效果,我们就要 保持X Y 的比值不变!

新增变量:
public Transform 瞄准点;
public float 初始PIP相机FOV = 60f;
public float pIP镜片初始大小;
float range;
在OnEnable中添加代码: range = Vector3.Distance(transform.position,瞄准点.position);

又在Update中设置PIP镜片的大小变化:
float scale = Vector3.Distance(当前相机.position, transform.position) / range;
pIP镜片.localScale = new Vector3(pIP镜片初始大小 * scale, pIP镜片初始大小 * scale, pIP镜片.localScale.z);
看看效果,大成功!!

最后一步,我们要给它添加“黑边”,看看上图,我们会发现现实中的狙击镜是有个模糊的圆形黑边的。
打开你的SAI或PS 做出类似以下两张图片,记住是透明背景的!(也许 可以在这里下载XD)


把他们导入PIP文件夹。
Texture Type 都选为Sprite。

创建一个Prefab 黑边,在下面增加两个空物体,分别名为黑边、黑边框。二者添加Sprite Renderer,把上文两张图分别拖进去,调整为如图(我调整黑边的缩放为(0.05,0.05,0.05))

保存预制体,拖入狙击镜的AimPoint下,把它的及其子物体的layer设置为PIP 。

我们又将其调整至合适的大小,并往前移动一段距离(要调整的是黑边的两个子物体哦!)。
这里我将两个子物体的scale大小都除以5,并将他两向正z轴至0.31个单位。

做完这些后,我们又继续写代码;在OpticalSight中新增变量:
[Header("黑框")]
public Transform 黑边;
public float 黑边初始大小;
public float 黑边最小值 = 1f;

我们又在update代码末端添加如下代码
if (黑边初始大小 / scale < 黑边最小值)
{
scale = 1 / 黑边最小值;
}
黑边.localScale = new Vector3(黑边初始大小 / scale, 黑边初始大小 / scale, 黑边.localScale.z);
黑边.forward = transform.forward;

然后在脚本上赋值。。。

这时我们要把pip镜片往前移(我将z轴移至-0.05),同时PPIPCamera的FOV也调为19,目的是为了黑边旋转时不会因为角度问题而穿过镜片,造成露馅。

不过这样子我们也要把黑边两个子物体的scale都再除以2:

看看效果吧!

本期教学到这里就结束了,懒得动手的可以直接在这里下载成品资源(其实上面也有):
(度盘链接传统开头https://pan.baidu.com/s/)1GrrFhoULDAiRJ3QaZ6eBwQ
TQ码:wt8c