Unity | 渡鸦避难所-5 | 角色和摄像机之间的遮挡物半透明

1 前言
角色在地图上移动到岩石后面时,完全被岩石遮挡,玩家只能看到岩石。这逻辑看起来没问题,但并不是玩家想要看到的画面,玩家更希望关注角色的状态

为了避免角色被遮挡,可以使用 Cinemachine Collider 功能,虚拟相机会自动避开障碍物,或者将角色和摄像机之间的障碍物做半透明处理,这两种方式的原理都是利用物理射线
这里使用障碍物半透明的方案,利用物理射线,检测角色和摄像机之间指定 Layer 的障碍物,改变其透明度,角色移动后,恢复其原本的透明度
2 设置 Layer
场景中的对象类型多种多样,我们仅希望岩石、树木等环境中的物体遮挡角色时,才改变其透明度。因此需要将对象分为不同的类型,利用 Unity 的 Layer 功能可以轻松实现该需求
Layer 定义哪些游戏对象可以与不同的功能以及彼此交互。它们主要有两种用途:由摄像机用来仅渲染场景的某一部分;由光源用来仅照亮场景的某些部分。但是,层也可以供射线投射用于选择性地忽略碰撞体或创建碰撞。更多信息请参阅文档:「https://docs.unity3d.com/cn/2021.2/Manual/Layers.html」
1 添加 Layer
这里偷个懒,只创建一个 Environment 层,就不再细分了


2 分配 Layer
将 Free_Forest 及其子对象均设置为 Environment 层

3 射线检测
在场景中从角色向摄像机投射一条射线,获取 Environment 层中所有命中的对象
脚本中获取 Environment 层的方式有两种
var layerMask = LayerMask.GetMask("Environment");
或者
var layerMask = 1 << LayerMask.NameToLayer("Environment");
通过角色和摄像机的位置计算出射线投射的方向和距离,利用 Physics.RaycastNonAlloc 来获取射线命中对象,相比 Physics.RaycastAll,此函数不会产生任何垃圾,毕竟在 FixedUpdate 中进行射线检测,应当尽量减少性能损耗
var size = Physics.RaycastNonAlloc(selfPosition, direction, this._raycastHits, rayDistance, layerMask);
获取命中对象中所有子节点的材质集合,和上一次命中的材质集合对比,改变其透明度
private void TransparentObjects()
{Vector3 selfPosition = transHead.position;Vector3 cameraPosition = _cameraTrans.position;var rayDistance = Vector3.Distance(selfPosition, cameraPosition);Vector3 direction = Vector3.Normalize(cameraPosition - selfPosition);Debug.DrawLine(selfPosition, cameraPosition, Color.red);var layerMask = LayerMask.GetMask("Environment");var size = Physics.RaycastNonAlloc(selfPosition, direction, this._raycastHits, rayDistance, layerMask);List<Material> materials = new List<Material>();for (int i = 0; i < size; i++){var meshRenderers = this._raycastHits[i].collider.GetComponentsInChildren<MeshRenderer>();foreach (var variable in meshRenderers){materials.AddRange(variable.materials);}}var transparentList = materials.Except(_materialList).ToList();var opaqueList = _materialList.Except(materials).ToList();foreach (var variable in transparentList){MaterialTransparent.SetMaterialTransparent(true, variable, 0.22f);}foreach (var variable in opaqueList){MaterialTransparent.SetMaterialTransparent(false, variable);}_materialList = materials;
}
4 更改透明度
由于性能等因素,默认情况下 3D 模型的材质是不支持更改透明度的。需要将材质的 Rendering Mode(对于内置渲染管线)或 Surface Type(对于 URP 或 HDRP)设置为 Transparent,才可以调整透明度相关的属性

这里我们需要更改的属性主要为:
-
Surface Type:控制材质是否支持透明度,更多信息,请参阅文档: 「https://docs.unity3d.com/cn/Packages/com.unity.render-pipelines.high-definition@7.4/manual/Surface-Type.html」
-
Opaque:模拟没有光线穿透的全实体材质。
-
Transparent:模拟光线可以穿透的半透明材质,例如透明塑料或玻璃。选择 Transparent 会在 Surface Options 部分中显示更多属性,还会显示一个额外的 Transparency Inputs 部分
-
-
Blend:确定 GPU 如何将片元着色器的输出与渲染目标进行合并,更多信息请参阅文档: 「https://docs.unity3d.com/cn/current/Manual/SL-Blend.html」
通过脚本更改 Surface Type 和 Blend 属性:
public class MaterialTransparent
{private enum SurfaceType{Opaque,Transparent}private enum BlendMode{Alpha,Premultiply,Additive,Multiply}public static void SetMaterialTransparent(bool transparent, Material material, float alpha = 1){if (transparent){material.SetFloat("_Surface", (float)SurfaceType.Transparent);material.SetFloat("_Blend", (float)BlendMode.Alpha);}else{material.SetFloat("_Surface", (float)SurfaceType.Opaque);}SetupMaterialBlendMode(material);Color color = material.color;color.a = alpha;material.color = color;}private static void SetupMaterialBlendMode(Material material){if (material == null){return;}bool alphaClip = material.GetFloat("_AlphaClip") == 1;if (alphaClip){material.EnableKeyword("_ALPHATEST_ON");}else{material.DisableKeyword("_ALPHATEST_ON");}SurfaceType surfaceType = (SurfaceType)material.GetFloat("_Surface");if (surfaceType == 0){material.SetOverrideTag("RenderType", "");material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.One);material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.Zero);material.SetInt("_ZWrite", 1);material.DisableKeyword("_ALPHAPREMULTIPLY_ON");material.renderQueue = -1;material.SetShaderPassEnabled("ShadowCaster", true);}else{BlendMode blendMode = (BlendMode)material.GetFloat("_Blend");switch (blendMode){case BlendMode.Alpha:material.SetOverrideTag("RenderType", "Transparent");material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.SrcAlpha);material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha);material.SetInt("_ZWrite", 0);material.DisableKeyword("_ALPHAPREMULTIPLY_ON");material.renderQueue = (int)UnityEngine.Rendering.RenderQueue.Transparent;material.SetShaderPassEnabled("ShadowCaster", false);break;case BlendMode.Premultiply:material.SetOverrideTag("RenderType", "Transparent");material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.One);material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha);material.SetInt("_ZWrite", 0);material.EnableKeyword("_ALPHAPREMULTIPLY_ON");material.renderQueue = (int)UnityEngine.Rendering.RenderQueue.Transparent;material.SetShaderPassEnabled("ShadowCaster", false);break;case BlendMode.Additive:material.SetOverrideTag("RenderType", "Transparent");material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.One);material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.One);material.SetInt("_ZWrite", 0);material.DisableKeyword("_ALPHAPREMULTIPLY_ON");material.renderQueue = (int)UnityEngine.Rendering.RenderQueue.Transparent;material.SetShaderPassEnabled("ShadowCaster", false);break;case BlendMode.Multiply:material.SetOverrideTag("RenderType", "Transparent");material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.DstColor);material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.Zero);material.SetInt("_ZWrite", 0);material.DisableKeyword("_ALPHAPREMULTIPLY_ON");material.renderQueue = (int)UnityEngine.Rendering.RenderQueue.Transparent;material.SetShaderPassEnabled("ShadowCaster", false);break;}}}
}
5 透明效果
最终效果如下图所示,角色走到岩石后面时,岩石呈现半透明状态

相关文章:
Unity | 渡鸦避难所-5 | 角色和摄像机之间的遮挡物半透明
1 前言 角色在地图上移动到岩石后面时,完全被岩石遮挡,玩家只能看到岩石。这逻辑看起来没问题,但并不是玩家想要看到的画面,玩家更希望关注角色的状态 为了避免角色被遮挡,可以使用 Cinemachine Collider 功能&#x…...
ResNet论文阅读和简单实现
论文:https://arxiv.org/pdf/1512.03385.pdf Deep Residual Learning for Image Recognition 本模块主要是阅读论文,会做简单的翻译(至少满足我自己能看明白)。 Introduction 由上图可见,在20层和56层的网络上训练的…...
QT上位机开发(数据库sqlite编程)
【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing 163.com】 编写软件的时候,如果用户的数据比较少,那么用json保存是非常方便的。但是一旦数据量大了之后,建议还是用数据库…...
在ARMv8中aarch64与aarch32切换
需求描述 在项目调试过程中,由于内存或磁盘空间不足需要将系统从aarch64切换到aarch32的运行状态去执行,接下来记录cortexA53的调试过程。 相关寄存器描述 ARM64: SPSR_EL3 N (Negative):表示运算结果的最高位,用于指示运算结果是否为负数。 Z (Zero):表示运算结果是否…...
拧巴的 tcp
本来想说说 tcp fastopen(tfo),但没什么意义,看 rfc7413 好了,还是 tcp 的惯常套路,引入一个新特性,解决了某个问题,带来一些新问题,然后就是各种 tradeoff,哪里适用哪里不适用。久而…...
java servlet 学生管理系统myeclipse开发oracle数据库BS模式java编程网
一、源码特点 java servlet 学生管理系统是一套完善的web设计系统,对理解JSP java编程开发语言有帮助servletbeandao (mvc模式开发),系统具有完整的源代码和数据库,开发环境为 TOMCAT7.0,Myeclipse8.5开发,数据库为Oracle 10g…...
使用buildx构建多架构镜像
使用buildx构建多架构镜像 1. 前置条件 docker 19.03以上版本 ubuntu 22.04 2. 安装相关组件 2.1 安装docker sudo apt-get updatesudo apt-get install \apt-transport-https \ca-certificates \curl \gnupg-agent \software-properties-commoncurl -fsSL https://mirrors.…...
Crow:run的流程4 准备接收http请求
完成tcp的accept后,下一步需要接收tcp的数据,同时完成http的分析 class Connection { public:void start(){adaptor_.start([this](const asio::error_code& ec) {if (!ec){start_deadline();parser_.clear();do_read();}else{CROW_LOG_ERROR << "Could not …...
Springboot集成RabbitMq一
0、知识点 1、创建项目-生产者 默认官方start.spring.io已不支持自动生成低版本jkd的Spring项目,自定义用阿里云的starter即可:https://start.aliyun.com 2、创建配置类 package com.wym.rabbitmqprovider.utils;import org.springframework.amqp.core.…...
零知识证明(zk-SNARK)- groth16(一)
全称为 Zero-Knowledge Succinct Non-Interactive Argument of Knowledge,简洁非交互式零知识证明,简洁性使得运行该协议时,即便 statement 非常大,它的 proof 大小也仅有几百个bytes,并且验证一个 proof 的时间可以达…...
Spring java和go并发的实现策略
Spring Java框架和Go框架在处理并发请求时采用了不同的策略。 1. Spring Java框架: Spring框架基于Java语言,通常使用线程池来处理并发请求。具体来说,Spring框架中的Servlet容器(如Tomcat、Jetty等)会使用线程池来管…...
第二十五章 JDBC 和数据库连接池
一、JDBC 概述(P821) 1. 基本介绍 (1)JDBC 为访问不同的数据库提供了统一的接口,为使用者屏蔽了细节问题。 (2)Java 程序员使用 JDBC,可以连接任何提供了 JDBC 驱动程序的数据库系统…...
Baumer工业相机堡盟工业相机如何通过NEOAPI SDK设置相机的固定帧率(C++)
Baumer工业相机堡盟工业相机如何通过NEOAPI SDK设置相机的固定帧率(C) Baumer工业相机Baumer工业相机的固定帧率功能的技术背景CameraExplorer如何查看相机固定帧率功能在NEOAPI SDK里通过函数设置相机固定帧率 Baumer工业相机通过NEOAPI SDK设置相机固定…...
基于Java课堂签到系统
基于Java课堂签到系统 功能需求 1、用户登录:学生需要使用学号或手机号等唯一标识登录系统。 2、签到功能:在课堂开始时,学生可以通过系统进行签到,以证明出席。 3、签出功能:在课堂结束时,学生可以通过…...
springboot整合webservice使用总结
因为做的项目中用到了webservice,所以在此总结一下。 一、webservice简介 Web Service也叫XML Web Service, WebService是一种可以接收从Internet或者Intranet上的其它系统中传递过来的请求,轻量级的独立的通讯技术。是通过SOAP在Web上提供的软件服务,使…...
MySQL中的索引之分类,原理,作用,优缺点和执行计划
索引 索引的作用:加速查找 例如: 300w条数据的表中查询,无索引需要700s, 利用索引可能只需要1s用索引的时机是,数据量巨大,并且搜索快速 索引为什么能实现加速查找 基于索引的内部存储结构索引底层基于 BTree 的数据结构存储的在…...
如何做好档案数字化前的鉴定工作
要做好档案数字化前的鉴定工作,可以按照以下步骤进行: 1. 确定鉴定目标:明确要鉴定的档案的内容、数量和性质,确定鉴定的范围和目标。 2. 进行档案清点:对档案进行全面清点和登记,包括数量、种类、状况等信…...
pytorch04:网络模型创建
目录 一、模型创建过程1.1 以LeNet网络为例1.2 LeNet结构1.3 nn.Module 二、网络层容器(Containers)2.1 nn.Sequential2.1.1 常规方法实现2.1.2 OrderedDict方法实现 2.2 nn.ModuleList2.3 nn.ModuleDict2.4 三种容器构建总结 三、AlexNet网络构建 一、模型创建过程 1.1 以LeNe…...
用js让用户输入一个数累加和
需求:用户输入一个数, 计算 1 到这个数的和。 比如 用户输入的是 5, 则计算 1~5 之间的累加和 并且输出到控制台 <body><script>let numprompt(请输入一个数)let sum0for(let i1;i<num;i){sumi}console.log(sum)</script…...
踩坑记录-安装nuxt3报错:Error: Failed to download template from registry: fetch failed;
报错复现 安装nuxt3报错:Error: Failed to download template from registry: fetch failednpx nuxi init nuxt-demo 初始化nuxt 项目 报错 Error: Failed to download template from registry: fetch faile 解决方法 配置hosts Mac电脑:/etc/hostswin电…...
Appium+python自动化(十六)- ADB命令
简介 Android 调试桥(adb)是多种用途的工具,该工具可以帮助你你管理设备或模拟器 的状态。 adb ( Android Debug Bridge)是一个通用命令行工具,其允许您与模拟器实例或连接的 Android 设备进行通信。它可为各种设备操作提供便利,如安装和调试…...
从WWDC看苹果产品发展的规律
WWDC 是苹果公司一年一度面向全球开发者的盛会,其主题演讲展现了苹果在产品设计、技术路线、用户体验和生态系统构建上的核心理念与演进脉络。我们借助 ChatGPT Deep Research 工具,对过去十年 WWDC 主题演讲内容进行了系统化分析,形成了这份…...
PHP和Node.js哪个更爽?
先说结论,rust完胜。 php:laravel,swoole,webman,最开始在苏宁的时候写了几年php,当时觉得php真的是世界上最好的语言,因为当初活在舒适圈里,不愿意跳出来,就好比当初活在…...
在rocky linux 9.5上在线安装 docker
前面是指南,后面是日志 sudo dnf config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo sudo dnf install docker-ce docker-ce-cli containerd.io -y docker version sudo systemctl start docker sudo systemctl status docker …...
04-初识css
一、css样式引入 1.1.内部样式 <div style"width: 100px;"></div>1.2.外部样式 1.2.1.外部样式1 <style>.aa {width: 100px;} </style> <div class"aa"></div>1.2.2.外部样式2 <!-- rel内表面引入的是style样…...
CMake控制VS2022项目文件分组
我们可以通过 CMake 控制源文件的组织结构,使它们在 VS 解决方案资源管理器中以“组”(Filter)的形式进行分类展示。 🎯 目标 通过 CMake 脚本将 .cpp、.h 等源文件分组显示在 Visual Studio 2022 的解决方案资源管理器中。 ✅ 支持的方法汇总(共4种) 方法描述是否推荐…...
docker 部署发现spring.profiles.active 问题
报错: org.springframework.boot.context.config.InvalidConfigDataPropertyException: Property spring.profiles.active imported from location class path resource [application-test.yml] is invalid in a profile specific resource [origin: class path re…...
管理学院权限管理系统开发总结
文章目录 🎓 管理学院权限管理系统开发总结 - 现代化Web应用实践之路📝 项目概述🏗️ 技术架构设计后端技术栈前端技术栈 💡 核心功能特性1. 用户管理模块2. 权限管理系统3. 统计报表功能4. 用户体验优化 🗄️ 数据库设…...
安宝特方案丨船舶智造的“AR+AI+作业标准化管理解决方案”(装配)
船舶制造装配管理现状:装配工作依赖人工经验,装配工人凭借长期实践积累的操作技巧完成零部件组装。企业通常制定了装配作业指导书,但在实际执行中,工人对指导书的理解和遵循程度参差不齐。 船舶装配过程中的挑战与需求 挑战 (1…...
基于IDIG-GAN的小样本电机轴承故障诊断
目录 🔍 核心问题 一、IDIG-GAN模型原理 1. 整体架构 2. 核心创新点 (1) 梯度归一化(Gradient Normalization) (2) 判别器梯度间隙正则化(Discriminator Gradient Gap Regularization) (3) 自注意力机制(Self-Attention) 3. 完整损失函数 二…...
