【unity小技巧】使用三种方式实现瞄准瞄具放大变焦效果

本文主要是介绍【unity小技巧】使用三种方式实现瞄准瞄具放大变焦效果,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

最终效果对比

在这里插入图片描述

文章目录

  • 最终效果对比
  • 前言
  • 第一种办法
  • 方法二
    • 1. 创建URP环境
    • 2. 配置 Universal Render Pipeline Asset
    • 3. 这里向我们新建一个无光的ShaderGraph
    • 4. 主图配置
    • 4. 新建材质,挂载
    • 5. 下面是shaderGraph 的连线图
    • 6. 新增脚本控制ObjectScreenPosition随着瞄准镜移动而不断修改
    • 6. 新增脚本控制_ZoomAmount实现滚轮放大缩小效果
  • 第三种办法
    • 1. 新增渲染相机
    • 2. 创建一个渲染纹理
    • 3. 绑定渲染纹理
    • 4. 解决镜片穿模问题
    • 5. 脚本控制实现放大缩小效果
  • 总结
  • 参考
  • 完结

前言

在许多射击类游戏中,瞄具的放大变焦效果是提高射击精准度和游戏体验的重要部分。Unity作为一款流行的游戏开发引擎,提供了多种实现瞄准瞄具放大变焦效果的方法。本文将介绍三种常见的实现方式,并分别探讨它们的优缺点。

首先,我们将介绍如何通过调整摄像机的视野来实现放大变焦效果。其次,我们将讨论如何利用Shader来实现瞄具的放大效果,以及如何使用Render Texture来模拟变焦效果。每种方法都有其独特的应用场景和适用性,在本文中,我们将深入探讨这三种方法的具体实现和使用场景,帮助开发者根据自身需求选择合适的实现方式。

无论您是初学者还是有经验的开发者,本文都将为您提供全面的教程和示例代码,帮助您更好地理解和运用Unity中的瞄具放大变焦效果。让我们开始探索这些令人兴奋的技术吧!

第一种办法

调节相机FOV值

public class RifleScopeZoom : MonoBehaviour
{[SerializeField] private Camera playerCamera;[SerializeField] private float zoomSpeed = 10f;[SerializeField] private float minFOV = 20f;[SerializeField] private float maxFOV = 60f;private void Update(){// 获取滚轮滑动的值float scrollValue = Input.GetAxis("Mouse ScrollWheel");// 根据滚轮滑动的值调整 FOVplayerCamera.fieldOfView -= scrollValue * zoomSpeed;// 限制 FOV 的范围在最小值和最大值之间playerCamera.fieldOfView = Mathf.Clamp(playerCamera.fieldOfView, minFOV, maxFOV);}
}

效果
在这里插入图片描述
这就是第一个实现方式,如你所见十分简单,它所作的就是调整主摄像机参数,这个方式的优点就是性能好,你不需要什么新Shader或者另一个相机,而只需要调整相机FOV,不过缺点就是不太好看,在理想情况下我们只会希望放大瞄准镜所看到的物体,不过现在整个画面都放大了

还有就是如果你的瞄准镜模型不是空心通透的可能无法使用这种方法,比如狙击枪的瞄准镜,我下面的例子就是,使用我只能去掉瞄准镜
在这里插入图片描述

方法二

对于第二个方法我们会需要用到Shader来放大某个物体背后的画面

1. 创建URP环境

如果不懂的可以看我之前的文章,有教具体如何配置URP环境:使用Shader Graph实现动物森友会的世界弯曲效果

2. 配置 Universal Render Pipeline Asset

由于实验中使用了 Scene Depth 和 Scene Color 节点获取深度缓冲区和颜色缓冲区信息,需要在 Universal Render Pipeline Asset 中勾选 Depth Texture 和 Opaque Texture,如下。
在这里插入图片描述

3. 这里向我们新建一个无光的ShaderGraph

在这里插入图片描述

4. 主图配置

由于镜子是透明的,需要在主图的 Graph Settings 中将 Surface Type 属性设置 Transparent
在这里插入图片描述

4. 新建材质,挂载

为了实现这个效果我在瞄准镜中放了个球,然后把它弄得很平,模拟一个镜面效果,绑定带前面ShaderGraph的材质
在这里插入图片描述

5. 下面是shaderGraph 的连线图

在这里插入图片描述
这里用了Scene Color节点它输出这个物体背后的场景颜色,然后用Tilling and offset节点修改其中的Tilling值来实现放大,然后就是用到物体屏幕坐标这个是最复杂的点ObjectScreenPosition,这个参数需要随着瞄准镜移动而不断修改。

6. 新增脚本控制ObjectScreenPosition随着瞄准镜移动而不断修改

因此我这里有另一个脚本RifleScopeShaderScreenPos,它的作用就是将物体世界坐标转屏幕坐标然后输入到Shader中,所以这个Shader不会放大所有画面,他只会放大瞄准镜里的东西

public class RifleScopeShaderScreenPos : MonoBehaviour
{// Shader 材质[SerializeField] private Material material;private void Update(){// 获取物体在屏幕上的像素坐标Vector2 screenPixels = Camera.main.WorldToScreenPoint(transform.position);// 将像素坐标转换为 0-1 的范围screenPixels = new Vector2(screenPixels.x / Screen.width, screenPixels.y / Screen.height);// 将物体的屏幕坐标传递给 Shadermaterial.SetVector("_ObjectScreenPosition", screenPixels);}
}

6. 新增脚本控制_ZoomAmount实现滚轮放大缩小效果

public class RifleScopeZoomMaterial : MonoBehaviour
{[SerializeField] private float zoomSpeed = 10f;[SerializeField] private float min  = 0f;[SerializeField] private float max = 1f;[SerializeField] private Material zoomMaterial;private void Update(){// 获取滚轮滑动的值float scrollValue = Input.GetAxis("Mouse ScrollWheel");scrollValue = zoomMaterial.GetFloat("_ZoomAmount") + scrollValue;// 限制的范围在最小值和最大值之间scrollValue = Mathf.Clamp(scrollValue, min, max);zoomMaterial.SetFloat("_ZoomAmount", scrollValue);}
}

在这里插入图片描述
和上一个方法相比优点就是它只放大瞄具所看到的东西,所以瞄具外的东西都不会变化,另一个优点就是相比于接下来的方法,这个方法不太吃性能,它只有一个Shader而且相机只渲染一次,当然也有缺点,有一个潜在的问题就是当你放大后画面会变成这样
在这里插入图片描述
当你放大倍率不是很高时画面凑合的过去,不过当你放的越大你就越会得到马赛克画面,这和画面的分辨率有关,Shader只是简单的放大了这个图片而不会改变它的分辨率,所以放的越大画面马赛克就会变明显,如果你放大的倍数不会太大这是个不错的方法,还有和前面有相同的问题,就是如果你的瞄准镜模型不是空心通透的可能不适合这种方法

第三种办法

我们得用一下渲染纹理特性,本质上来说就是可以把相机的画面渲染到一个纹理上

1. 新增渲染相机

所以我们需要一个新的相机,然后把它往前面拖一下,现在你可以把它拖到瞄准镜前面或者直接放在枪管上,然后通过拉低FOV来放大画面
在这里插入图片描述

2. 创建一个渲染纹理

我们再创建一个渲染纹理,这边主要设置一下尺寸,这主要取决于玩家分辨率以及瞄准镜在屏幕上的大小,这里1024*1024差不多够了

在这里插入图片描述
这样子我们就设置好了接下来让相机把渲染画面输出到这个纹理上
在这里插入图片描述
这样我门就能看到相机的画面己经渲染到这张纹理之中了
在这里插入图片描述

3. 绑定渲染纹理

接下来为了在瞄准镜中显示画面,我们直接在瞄准镜里边放一个Quad,我们只需要把渲染纹理拖进来就能得到瞄具画面了
在这里插入图片描述
这样就有效果了,下面就是放大后的相机画面了
在这里插入图片描述

4. 解决镜片穿模问题

不过还是有个小小的问题,那就是我门的Quad是方形的而瞄准镜是圆形的,所以你会看到它有些穿模了
在这里插入图片描述
一个很简单的解决办法就是只需要做一个透明度裁剪
在这里插入图片描述
这里也有个透明度裁剪预制,只需要确保你到设置面板理启出Alpha clip
在这里插入图片描述
做完之后点击这边的AlphaClipMask选择一张带透明背景的圆形贴图
在这里插入图片描述
完了之后你会看到遮罩外边的贴图被裁减了它只保留了中间的画面
在这里插入图片描述

5. 脚本控制实现放大缩小效果

最后一步就是要处理脚本了,我们要做的就是调整渲染纹理相机的FOV,可以复用前面的代码,不够记得把相机修改为我们的渲染相机,而不是主相机

public class RifleScopeZoom : MonoBehaviour
{[SerializeField] private Camera playerCamera;[SerializeField] private float zoomSpeed = 10f;[SerializeField] private float minFOV = 20f;[SerializeField] private float maxFOV = 60f;private void Update(){// 获取滚轮滑动的值float scrollValue = Input.GetAxis("Mouse ScrollWheel");// 根据滚轮滑动的值调整 FOVplayerCamera.fieldOfView -= scrollValue * zoomSpeed;// 限制 FOV 的范围在最小值和最大值之间playerCamera.fieldOfView = Mathf.Clamp(playerCamera.fieldOfView, minFOV, maxFOV);}
}

效果
在这里插入图片描述
我可以放大我想要的地方,如你所见和上一个方法相比没有马赛克问题,而且这个方法有一个有趣的特性,那就是即使我枪没有抬起来时瞄具上的画面也在变化
在这里插入图片描述
另一个优点就是由于我使用了另一个相机,因此我可以做一些有趣的东西,比如我可以用不同的后处理效果,我可以在主相机上加上景深效果,由于渲染纹理离相机很近所以它没被模糊化而外边的东西都模糊掉了
在这里插入图片描述

在这里插入图片描述
就个人而言这个观感效果最好,瞄具外的画面被模糊掉了但内部的画面仍然很清楚,如果你想的话你可以把镜子往前放一放来用其他的后处理效果,你可以实现镜内热成像或者夜视效果而镜外画面保持正常。

当然了这个方法也有一个大缺点那就是性能问题,这个方式使用渲染纹理来显示第二个相机的画面,本质上画面被渲染了2次,如果你做的游戏是PC端这可能不会是个大问题,而如果是手游的话可能就是大问题了,如果你可以承受性能代价,这个方法是最好的一个。

总结

好了你已经学完这三个瞄准镜放大方法了,第一个方法适合性能优先需求或者想找最简单实现方式的人,第二个方法稍优于第一
而最后一个你会得到最好的瞄具效果,去选一个适合的方法用在你的项目里吧!
在这里插入图片描述

参考

【视频】https://www.youtube.com/watch?v=9g2VqJvWnQI

完结

赠人玫瑰,手有余香!如果文章内容对你有所帮助,请不要吝啬你的点赞评论和关注,以便我第一时间收到反馈,你的每一次支持都是我不断创作的最大动力。当然如果你发现了文章中存在错误或者有更好的解决方法,也欢迎评论私信告诉我哦!

好了,我是向宇,https://xiangyu.blog.csdn.net

一位在小公司默默奋斗的开发者,出于兴趣爱好,最近开始自学unity,闲暇之余,边学习边记录分享,站在巨人的肩膀上,通过学习前辈们的经验总是会给我很多帮助和启发!php是工作,unity是生活!如果你遇到任何问题,也欢迎你评论私信找我, 虽然有些问题我也不一定会,但是我会查阅各方资料,争取给出最好的建议,希望可以帮助更多想学编程的人,共勉~

在这里插入图片描述

这篇关于【unity小技巧】使用三种方式实现瞄准瞄具放大变焦效果的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/506139

相关文章

mtu设置多少网速最快? 路由器MTU设置最佳网速的技巧

《mtu设置多少网速最快?路由器MTU设置最佳网速的技巧》mtu设置多少网速最快?想要通过设置路由器mtu获得最佳网速,该怎么设置呢?下面我们就来看看路由器MTU设置最佳网速的技巧... 答:1500 MTU值指的是在网络传输中数据包的最大值,合理的设置MTU 值可以让网络更快!mtu设置可以优化不同的网

Python并行处理实战之如何使用ProcessPoolExecutor加速计算

《Python并行处理实战之如何使用ProcessPoolExecutor加速计算》Python提供了多种并行处理的方式,其中concurrent.futures模块的ProcessPoolExecu... 目录简介完整代码示例代码解释1. 导入必要的模块2. 定义处理函数3. 主函数4. 生成数字列表5.

Python中help()和dir()函数的使用

《Python中help()和dir()函数的使用》我们经常需要查看某个对象(如模块、类、函数等)的属性和方法,Python提供了两个内置函数help()和dir(),它们可以帮助我们快速了解代... 目录1. 引言2. help() 函数2.1 作用2.2 使用方法2.3 示例(1) 查看内置函数的帮助(

Linux脚本(shell)的使用方式

《Linux脚本(shell)的使用方式》:本文主要介绍Linux脚本(shell)的使用方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录概述语法详解数学运算表达式Shell变量变量分类环境变量Shell内部变量自定义变量:定义、赋值自定义变量:引用、修改、删

Python实现精准提取 PDF中的文本,表格与图片

《Python实现精准提取PDF中的文本,表格与图片》在实际的系统开发中,处理PDF文件不仅限于读取整页文本,还有提取文档中的表格数据,图片或特定区域的内容,下面我们来看看如何使用Python实... 目录安装 python 库提取 PDF 文本内容:获取整页文本与指定区域内容获取页面上的所有文本内容获取

基于Python实现一个Windows Tree命令工具

《基于Python实现一个WindowsTree命令工具》今天想要在Windows平台的CMD命令终端窗口中使用像Linux下的tree命令,打印一下目录结构层级树,然而还真有tree命令,但是发现... 目录引言实现代码使用说明可用选项示例用法功能特点添加到环境变量方法一:创建批处理文件并添加到PATH1

Java使用HttpClient实现图片下载与本地保存功能

《Java使用HttpClient实现图片下载与本地保存功能》在当今数字化时代,网络资源的获取与处理已成为软件开发中的常见需求,其中,图片作为网络上最常见的资源之一,其下载与保存功能在许多应用场景中都... 目录引言一、Apache HttpClient简介二、技术栈与环境准备三、实现图片下载与保存功能1.

Python中使用uv创建环境及原理举例详解

《Python中使用uv创建环境及原理举例详解》uv是Astral团队开发的高性能Python工具,整合包管理、虚拟环境、Python版本控制等功能,:本文主要介绍Python中使用uv创建环境及... 目录一、uv工具简介核心特点:二、安装uv1. 通过pip安装2. 通过脚本安装验证安装:配置镜像源(可

python判断文件是否存在常用的几种方式

《python判断文件是否存在常用的几种方式》在Python中我们在读写文件之前,首先要做的事情就是判断文件是否存在,否则很容易发生错误的情况,:本文主要介绍python判断文件是否存在常用的几种... 目录1. 使用 os.path.exists()2. 使用 os.path.isfile()3. 使用

LiteFlow轻量级工作流引擎使用示例详解

《LiteFlow轻量级工作流引擎使用示例详解》:本文主要介绍LiteFlow是一个灵活、简洁且轻量的工作流引擎,适合用于中小型项目和微服务架构中的流程编排,本文给大家介绍LiteFlow轻量级工... 目录1. LiteFlow 主要特点2. 工作流定义方式3. LiteFlow 流程示例4. LiteF