【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

相关文章

Ilya-AI分享的他在OpenAI学习到的15个提示工程技巧

Ilya(不是本人,claude AI)在社交媒体上分享了他在OpenAI学习到的15个Prompt撰写技巧。 以下是详细的内容: 提示精确化:在编写提示时,力求表达清晰准确。清楚地阐述任务需求和概念定义至关重要。例:不用"分析文本",而用"判断这段话的情感倾向:积极、消极还是中性"。 快速迭代:善于快速连续调整提示。熟练的提示工程师能够灵活地进行多轮优化。例:从"总结文章"到"用

中文分词jieba库的使用与实景应用(一)

知识星球:https://articles.zsxq.com/id_fxvgc803qmr2.html 目录 一.定义: 精确模式(默认模式): 全模式: 搜索引擎模式: paddle 模式(基于深度学习的分词模式): 二 自定义词典 三.文本解析   调整词出现的频率 四. 关键词提取 A. 基于TF-IDF算法的关键词提取 B. 基于TextRank算法的关键词提取

使用SecondaryNameNode恢复NameNode的数据

1)需求: NameNode进程挂了并且存储的数据也丢失了,如何恢复NameNode 此种方式恢复的数据可能存在小部分数据的丢失。 2)故障模拟 (1)kill -9 NameNode进程 [lytfly@hadoop102 current]$ kill -9 19886 (2)删除NameNode存储的数据(/opt/module/hadoop-3.1.4/data/tmp/dfs/na

Hadoop数据压缩使用介绍

一、压缩原则 (1)运算密集型的Job,少用压缩 (2)IO密集型的Job,多用压缩 二、压缩算法比较 三、压缩位置选择 四、压缩参数配置 1)为了支持多种压缩/解压缩算法,Hadoop引入了编码/解码器 2)要在Hadoop中启用压缩,可以配置如下参数

Makefile简明使用教程

文章目录 规则makefile文件的基本语法:加在命令前的特殊符号:.PHONY伪目标: Makefilev1 直观写法v2 加上中间过程v3 伪目标v4 变量 make 选项-f-n-C Make 是一种流行的构建工具,常用于将源代码转换成可执行文件或者其他形式的输出文件(如库文件、文档等)。Make 可以自动化地执行编译、链接等一系列操作。 规则 makefile文件

hdu1043(八数码问题,广搜 + hash(实现状态压缩) )

利用康拓展开将一个排列映射成一个自然数,然后就变成了普通的广搜题。 #include<iostream>#include<algorithm>#include<string>#include<stack>#include<queue>#include<map>#include<stdio.h>#include<stdlib.h>#include<ctype.h>#inclu

使用opencv优化图片(画面变清晰)

文章目录 需求影响照片清晰度的因素 实现降噪测试代码 锐化空间锐化Unsharp Masking频率域锐化对比测试 对比度增强常用算法对比测试 需求 对图像进行优化,使其看起来更清晰,同时保持尺寸不变,通常涉及到图像处理技术如锐化、降噪、对比度增强等 影响照片清晰度的因素 影响照片清晰度的因素有很多,主要可以从以下几个方面来分析 1. 拍摄设备 相机传感器:相机传

【C++】_list常用方法解析及模拟实现

相信自己的力量,只要对自己始终保持信心,尽自己最大努力去完成任何事,就算事情最终结果是失败了,努力了也不留遗憾。💓💓💓 目录   ✨说在前面 🍋知识点一:什么是list? •🌰1.list的定义 •🌰2.list的基本特性 •🌰3.常用接口介绍 🍋知识点二:list常用接口 •🌰1.默认成员函数 🔥构造函数(⭐) 🔥析构函数 •🌰2.list对象

【Prometheus】PromQL向量匹配实现不同标签的向量数据进行运算

✨✨ 欢迎大家来到景天科技苑✨✨ 🎈🎈 养成好习惯,先赞后看哦~🎈🎈 🏆 作者简介:景天科技苑 🏆《头衔》:大厂架构师,华为云开发者社区专家博主,阿里云开发者社区专家博主,CSDN全栈领域优质创作者,掘金优秀博主,51CTO博客专家等。 🏆《博客》:Python全栈,前后端开发,小程序开发,人工智能,js逆向,App逆向,网络系统安全,数据分析,Django,fastapi

让树莓派智能语音助手实现定时提醒功能

最初的时候是想直接在rasa 的chatbot上实现,因为rasa本身是带有remindschedule模块的。不过经过一番折腾后,忽然发现,chatbot上实现的定时,语音助手不一定会有响应。因为,我目前语音助手的代码设置了长时间无应答会结束对话,这样一来,chatbot定时提醒的触发就不会被语音助手获悉。那怎么让语音助手也具有定时提醒功能呢? 我最后选择的方法是用threading.Time