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

相关文章

python获取指定名字的程序的文件路径的两种方法

《python获取指定名字的程序的文件路径的两种方法》本文主要介绍了python获取指定名字的程序的文件路径的两种方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要... 最近在做项目,需要用到给定一个程序名字就可以自动获取到这个程序在Windows系统下的绝对路径,以下

SpringBoot实现不同接口指定上传文件大小的具体步骤

《SpringBoot实现不同接口指定上传文件大小的具体步骤》:本文主要介绍在SpringBoot中通过自定义注解、AOP拦截和配置文件实现不同接口上传文件大小限制的方法,强调需设置全局阈值远大于... 目录一  springboot实现不同接口指定文件大小1.1 思路说明1.2 工程启动说明二 具体实施2

Three.js构建一个 3D 商品展示空间完整实战项目

《Three.js构建一个3D商品展示空间完整实战项目》Three.js是一个强大的JavaScript库,专用于在Web浏览器中创建3D图形,:本文主要介绍Three.js构建一个3D商品展... 目录引言项目核心技术1. 项目架构与资源组织2. 多模型切换、交互热点绑定3. 移动端适配与帧率优化4. 可

MySQL中查询和展示LONGBLOB类型数据的技巧总结

《MySQL中查询和展示LONGBLOB类型数据的技巧总结》在MySQL中LONGBLOB是一种二进制大对象(BLOB)数据类型,用于存储大量的二进制数据,:本文主要介绍MySQL中查询和展示LO... 目录前言1. 查询 LONGBLOB 数据的大小2. 查询并展示 LONGBLOB 数据2.1 转换为十

Unity新手入门学习殿堂级知识详细讲解(图文)

《Unity新手入门学习殿堂级知识详细讲解(图文)》Unity是一款跨平台游戏引擎,支持2D/3D及VR/AR开发,核心功能模块包括图形、音频、物理等,通过可视化编辑器与脚本扩展实现开发,项目结构含A... 目录入门概述什么是 UnityUnity引擎基础认知编辑器核心操作Unity 编辑器项目模式分类工程

C#和Unity中的中介者模式使用方式

《C#和Unity中的中介者模式使用方式》中介者模式通过中介者封装对象交互,降低耦合度,集中控制逻辑,适用于复杂系统组件交互场景,C#中可用事件、委托或MediatR实现,提升可维护性与灵活性... 目录C#中的中介者模式详解一、中介者模式的基本概念1. 定义2. 组成要素3. 模式结构二、中介者模式的特点

java -jar example.jar 产生的日志输出到指定文件的方法

《java-jarexample.jar产生的日志输出到指定文件的方法》这篇文章给大家介绍java-jarexample.jar产生的日志输出到指定文件的方法,本文给大家介绍的非常详细,对大家的... 目录怎么让 Java -jar example.jar 产生的日志输出到指定文件一、方法1:使用重定向1、

基于Python实现数字限制在指定范围内的五种方式

《基于Python实现数字限制在指定范围内的五种方式》在编程中,数字范围限制是常见需求,无论是游戏开发中的角色属性值、金融计算中的利率调整,还是传感器数据处理中的异常值过滤,都需要将数字控制在合理范围... 目录引言一、基础条件判断法二、数学运算巧解法三、装饰器模式法四、自定义类封装法五、NumPy数组处理

Windows环境下解决Matplotlib中文字体显示问题的详细教程

《Windows环境下解决Matplotlib中文字体显示问题的详细教程》本文详细介绍了在Windows下解决Matplotlib中文显示问题的方法,包括安装字体、更新缓存、配置文件设置及编码調整,并... 目录引言问题分析解决方案详解1. 检查系统已安装字体2. 手动添加中文字体(以SimHei为例)步骤

Golang如何对cron进行二次封装实现指定时间执行定时任务

《Golang如何对cron进行二次封装实现指定时间执行定时任务》:本文主要介绍Golang如何对cron进行二次封装实现指定时间执行定时任务问题,具有很好的参考价值,希望对大家有所帮助,如有错误... 目录背景cron库下载代码示例【1】结构体定义【2】定时任务开启【3】使用示例【4】控制台输出总结背景