Unity中物体半透明显示——e.g.让指定的构件从所有构件中脱颖而地展示自我

本文主要是介绍Unity中物体半透明显示——e.g.让指定的构件从所有构件中脱颖而地展示自我,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

一、要达到的效果

用户点击【走廊】菜单的时候,其他部件穿透显示,只有走廊正常显示,并高亮闪烁。
请添加图片描述

二、思路

  • 1、读取材质信息:读取各个部件的材质信息并存储,恢复材质的时候用
  • 2、设置物体为透明:把物体原来的材质换成透明材质
  • 3、取消物体的透明:把物体的透明材质换成原来的材质

三、关键步骤的代码

  • 只列了关键的方法

1、提取物体的材质生成一个字典

    /// <summary>/// 给定一个设备(3d物体root),遍历该物体的所有子部件(子部件的root名字包含[#],命名格式如【#部件名字】),读取子部件物体的材质信息,返回一个字典:/// Dictionary<string-部件的物体名字, List<(GameObject, Material[])-物体和它的材质数组>>/// key用物体名字是用来快速提取某个子部件的材质信息,用于更换材质或者恢复材质/// /// 层级关系及命名/// root///     #部件1///        gameobject1///        gameobject2///        ...///        gameobjectn///     ...///     #部件n/// /// </summary>/// <param name="root">3d物体——部件的root</param>/// <returns> Dictionary<string-子部件名字, List<(GameObject -- 子部件的子物体, Material[] -- 物体对应的材质数组)>>  </returns>static Dictionary<string, List<(GameObject, Material[])>> GetMaterialsDict(GameObject root){//提前生成空的返回值var partsMaterialDict = new Dictionary<string, List<(GameObject, Material[])>>();//获取所有的零件var parts = root.GetComponentsInChildren<Transform>(true).Where(x => x.name.Contains('$')).ToList();Debug.Log(parts.Count);Debug.Log(parts.Select(x => x.name.Split('$')[1]).First());parts.ForEach(x => Debug.Log(x.name.Split('$')[1]));//每个零件获取它的子物体的材质信息parts.ForEach(part =>{var partName = part.name.Split('$')[1];List<(GameObject, Material[])> goMatList = new List<(GameObject, Material[])>();part.GetComponentsInChildren<Transform>().ToList().ForEach(p =>{//Debug.Log(p.GetComponent<Renderer>());if (p.GetComponent<Renderer>() != null){goMatList.Add((p.gameObject, p.GetComponent<Renderer>().materials));}});partsMaterialDict[partName] = goMatList;});partsMaterialDict.Keys.ToList().ForEach(x =>{Debug.Log($"======{x}====== {partsMaterialDict[x].Count}");});return partsMaterialDict;}

2、其它物体设置成半透明

var partsMaterialDict = GetMaterialsDict(root);  //设备零部件的的父节点
 partsMaterialDict.ToList().Where(x => x.Key != name)   //给定的名字.SelectMany(x => x.Value).ToList().ForEach(x =>{//x.Item1.GetComponent<MeshRenderer>().sharedMaterials = new Material[] { transMat }; //此处有bug,数量要做一致x.Item1.GetComponent<MeshRenderer>().sharedMaterials = x.Item1.GetComponent<MeshRenderer>().sharedMaterials.Select(x => transMat).ToArray();//生成对数量的透明材质数组}); 

3、所有物体设置为正常材质

partsMaterialDict.ToList().SelectMany(x => x.Value).ToList()   //展开成1d数组.ForEach(x => x.Item1.GetComponent<MeshRenderer>().sharedMaterials = x.Item2);

4、展示一个部件

  • 1、显示全貌
  • 2、等待1秒
  • 3、其它半透明显示,自己正常显示,且高亮
 /// <summary>/// 显示指定的构件/// 指定构件从所有构件中脱颖而出(其他的透明显示,自己正常显示),高亮显示自己。/// 1、显示全貌/// 2、其它半透明显示,自己正常显示,且高亮/// </summary>/// <param name="name">部件名字</param>/// <param name="partsMaterialDict">部件的【物体】【材质信息】字典</param>/// <param name="transMat">透明材质</param>/// <param name="partsInfos">部件信息表</param>/// <returns>UniTask</returns>public static async UniTask Show(string name, Dictionary<string, List<(GameObject, Material[])>> partsMaterialDict, Material transMat, List<PartsInfo> partsInfos){//【1】显示所有【还原材质】partsMaterialDict.ToList().SelectMany(x => x.Value).ToList().ForEach(x => x.Item1.GetComponent<MeshRenderer>().sharedMaterials = x.Item2);//【2】关闭所有的高亮partsInfos.ForEach(x => x.part3D.GetComponent<Highlighter>().tween = false);await UniTask.Delay(TimeSpan.FromSeconds(1));//【3】其它半透明partsMaterialDict.ToList().Where(x => x.Key != name).SelectMany(x => x.Value).ToList().ForEach(x =>{//x.Item1.GetComponent<MeshRenderer>().sharedMaterials = new Material[] { transMat }; //此处有bug,数量要做一致x.Item1.GetComponent<MeshRenderer>().sharedMaterials = x.Item1.GetComponent<MeshRenderer>().sharedMaterials.Select(x => transMat).ToArray();//生成对数量的透明材质数组});//【4】自己高亮显示        partsInfos.Where(x => x.name == name).First().part3D.GetComponent<Highlighter>().tween = true;}

5、其它用到的数据结构

   /// <summary>/// 构件信息/// </summary>[Serializable]public class PartsInfo{/// <summary>/// 构件名字/// </summary>[Header("构件名字")][SerializeField]public string name;/// <summary>/// 菜单button/// </summary>[Header("菜单button")][SerializeField]public Button button;/// <summary>/// 构件的3D物体/// </summary>[Header("构件的3D物体")][SerializeField]public GameObject part3D;/// <summary>/// 是否学习过/// </summary>[Header("是否学习过")][SerializeField]public bool hasStudied;}/// <summary>/// 部件信息表/// </summary>[Header("部件信息表")][SerializeField]public List<PartsInfo> partsInfos = new List<PartsInfo>();

这篇关于Unity中物体半透明显示——e.g.让指定的构件从所有构件中脱颖而地展示自我的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



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

相关文章

使用Navicat工具比对两个数据库所有表结构的差异案例详解

《使用Navicat工具比对两个数据库所有表结构的差异案例详解》:本文主要介绍如何使用Navicat工具对比两个数据库test_old和test_new,并生成相应的DDLSQL语句,以便将te... 目录概要案例一、如图两个数据库test_old和test_new进行比较:二、开始比较总结概要公司存在多

使用Python合并 Excel单元格指定行列或单元格范围

《使用Python合并Excel单元格指定行列或单元格范围》合并Excel单元格是Excel数据处理和表格设计中的一项常用操作,本文将介绍如何通过Python合并Excel中的指定行列或单... 目录python Excel库安装Python合并Excel 中的指定行Python合并Excel 中的指定列P

如何设置vim永久显示行号

《如何设置vim永久显示行号》在Linux环境下,vim默认不显示行号,这在程序编译出错时定位错误语句非常不便,通过修改vim配置文件vimrc,可以在每次打开vim时永久显示行号... 目录设置vim永久显示行号1.临时显示行号2.永www.chinasem.cn久显示行号总结设置vim永久显示行号在li

Python将大量遥感数据的值缩放指定倍数的方法(推荐)

《Python将大量遥感数据的值缩放指定倍数的方法(推荐)》本文介绍基于Python中的gdal模块,批量读取大量多波段遥感影像文件,分别对各波段数据加以数值处理,并将所得处理后数据保存为新的遥感影像... 本文介绍基于python中的gdal模块,批量读取大量多波段遥感影像文件,分别对各波段数据加以数值处

在MyBatis的XML映射文件中<trim>元素所有场景下的完整使用示例代码

《在MyBatis的XML映射文件中<trim>元素所有场景下的完整使用示例代码》在MyBatis的XML映射文件中,trim元素用于动态添加SQL语句的一部分,处理前缀、后缀及多余的逗号或连接符,示... 在MyBATis的XML映射文件中,<trim>元素用于动态地添加SQL语句的一部分,例如SET或W

C#实现获得某个枚举的所有名称

《C#实现获得某个枚举的所有名称》这篇文章主要为大家详细介绍了C#如何实现获得某个枚举的所有名称,文中的示例代码讲解详细,具有一定的借鉴价值,有需要的小伙伴可以参考一下... C#中获得某个枚举的所有名称using System;using System.Collections.Generic;usi

通过C#获取PDF中指定文本或所有文本的字体信息

《通过C#获取PDF中指定文本或所有文本的字体信息》在设计和出版行业中,字体的选择和使用对最终作品的质量有着重要影响,然而,有时我们可能会遇到包含未知字体的PDF文件,这使得我们无法准确地复制或修改文... 目录引言C# 获取PDF中指定文本的字体信息C# 获取PDF文档中用到的所有字体信息引言在设计和出

多模块的springboot项目发布指定模块的脚本方式

《多模块的springboot项目发布指定模块的脚本方式》该文章主要介绍了如何在多模块的SpringBoot项目中发布指定模块的脚本,作者原先的脚本会清理并编译所有模块,导致发布时间过长,通过简化脚本... 目录多模块的springboot项目发布指定模块的脚本1、不计成本地全部发布2、指定模块发布总结多模

VMWare报错“指定的文件不是虚拟磁盘“或“The file specified is not a virtual disk”问题

《VMWare报错“指定的文件不是虚拟磁盘“或“Thefilespecifiedisnotavirtualdisk”问题》文章描述了如何修复VMware虚拟机中出现的“指定的文件不是虚拟... 目录VMWare报错“指定的文件不是虚拟磁盘“或“The file specified is not a virt

Oracle Expdp按条件导出指定表数据的方法实例

《OracleExpdp按条件导出指定表数据的方法实例》:本文主要介绍Oracle的expdp数据泵方式导出特定机构和时间范围的数据,并通过parfile文件进行条件限制和配置,文中通过代码介绍... 目录1.场景描述 2.方案分析3.实验验证 3.1 parfile文件3.2 expdp命令导出4.总结