这周有个需求是实现控制指示灯亮灭的效果。实现起来很简单,但是找到这个方法还费了点时间。
先看效果。

原理是利用了标准着色器中的自发光属性,通过开关自发光属性来控制灯的亮灭。
具体看步骤:
1.创建一个自发光的材质球,合理设置主要颜色与自发光颜色,金属度Metallic与平滑度Smoothness自己看需求设置

2.再创建一个无自发光的材质球

3.如何用代码控制自发光的开关内?
若不想了解从哪儿找到控制的地方的,这一段可以跳过,直接看工程。
既然在编辑器能够勾选自发光,那一定有一个编辑器脚本可以控制这部分。那么这个编辑器脚本在哪儿呢?你需要从unity官网下载你对应版本的内置着色器源码,下载回来的文件夹中Editor文件夹下的StandardShaderGUI.cs即是标准着色器编辑器的源码。

// Unity built-in shader source. Copyright (c) 2016 Unity Technologies. MIT license (see license.txt)using System;
using UnityEngine;namespace UnityEditor
{internal class StandardShaderGUI : ShaderGUI{private enum WorkflowMode{Specular,Metallic,Dielectric}public enum BlendMode{Opaque,Cutout,Fade,   // Old school alpha-blending mode, fresnel does not affect amount of transparencyTransparent // Physically plausible transparency mode, implemented as alpha pre-multiply}public enum SmoothnessMapChannel{SpecularMetallicAlpha,AlbedoAlpha,}private static class Styles{public static GUIContent uvSetLabel = new GUIContent("UV Set");public static GUIContent albedoText = new GUIContent("Albedo", "Albedo (RGB) and Transparency (A)");public static GUIContent alphaCutoffText = new GUIContent("Alpha Cutoff", "Threshold for alpha cutoff");public static GUIContent specularMapText = new GUIContent("Specular", "Specular (RGB) and Smoothness (A)");public static GUIContent metallicMapText = new GUIContent("Metallic", "Metallic (R) and Smoothness (A)");public static GUIContent smoothnessText = new GUIContent("Smoothness", "Smoothness value");public static GUIContent smoothnessScaleText = new GUIContent("Smoothness", "Smoothness scale factor");public static GUIContent smoothnessMapChannelText = new GUIContent("Source", "Smoothness texture and channel");public static GUIContent highlightsText = new GUIContent("Specular Highlights", "Specular Highlights");public static GUIContent reflectionsText = new GUIContent("Reflections", "Glossy Reflections");public static GUIContent normalMapText = new GUIContent("Normal Map", "Normal Map");public static GUIContent heightMapText = new GUIContent("Height Map", "Height Map (G)");public static GUIContent occlusionText = new GUIContent("Occlusion", "Occlusion (G)");public static GUIContent emissionText = new GUIContent("Color", "Emission (RGB)");public static GUIContent detailMaskText = new GUIContent("Detail Mask", "Mask for Secondary Maps (A)");public static GUIContent detailAlbedoText = new GUIContent("Detail Albedo x2", "Albedo (RGB) multiplied by 2");public static GUIContent detailNormalMapText = new GUIContent("Normal Map", "Normal Map");public static string primaryMapsText = "Main Maps";public static string secondaryMapsText = "Secondary Maps";public static string forwardText = "Forward Rendering Options";public static string renderingMode = "Rendering Mode";public static string advancedText = "Advanced Options";public static GUIContent emissiveWarning = new GUIContent("Emissive value is animated but the material has not been configured to support emissive. Please make sure the material itself has some amount of emissive.");public static readonly string[] blendNames = Enum.GetNames(typeof(BlendMode));}MaterialProperty blendMode = null;MaterialProperty albedoMap = null;MaterialProperty albedoColor = null;MaterialProperty alphaCutoff = null;MaterialProperty specularMap = null;MaterialProperty specularColor = null;MaterialProperty metallicMap = null;MaterialProperty metallic = null;MaterialProperty smoothness = null;MaterialProperty smoothnessScale = null;MaterialProperty smoothnessMapChannel = null;MaterialProperty highlights = null;MaterialProperty reflections = null;MaterialProperty bumpScale = null;MaterialProperty bumpMap = null;MaterialProperty occlusionStrength = null;MaterialProperty occlusionMap = null;MaterialProperty heigtMapScale = null;MaterialProperty heightMap = null;MaterialProperty emissionColorForRendering = null;MaterialProperty emissionMap = null;MaterialProperty detailMask = null;MaterialProperty detailAlbedoMap = null;MaterialProperty detailNormalMapScale = null;MaterialProperty detailNormalMap = null;MaterialProperty uvSetSecondary = null;MaterialEditor m_MaterialEditor;WorkflowMode m_WorkflowMode = WorkflowMode.Specular;ColorPickerHDRConfig m_ColorPickerHDRConfig = new ColorPickerHDRConfig(0f, 99f, 1 / 99f, 3f);bool m_FirstTimeApply = true;public void FindProperties(MaterialProperty[] props){blendMode = FindProperty("_Mode", props);albedoMap = FindProperty("_MainTex", props);albedoColor = FindProperty("_Color", props);alphaCutoff = FindProperty("_Cutoff", props);specularMap = FindProperty("_SpecGlossMap", props, false);specularColor = FindProperty("_SpecColor", props, false);metallicMap = FindProperty("_MetallicGlossMap", props, false);metallic = FindProperty("_Metallic", props, false);if (specularMap != null && specularColor != null)m_WorkflowMode = WorkflowMode.Specular;else if (metallicMap != null && metallic != null)m_WorkflowMode = WorkflowMode.Metallic;elsem_WorkflowMode = WorkflowMode.Dielectric;smoothness = FindProperty("_Glossiness", props);smoothnessScale = FindProperty("_GlossMapScale", props, false);smoothnessMapChannel = FindProperty("_SmoothnessTextureChannel", props, false);highlights = FindProperty("_SpecularHighlights", props, false);reflections = FindProperty("_GlossyReflections", props, false);bumpScale = FindProperty("_BumpScale", props);bumpMap = FindProperty("_BumpMap", props);heigtMapScale = FindProperty("_Parallax", props);heightMap = FindProperty("_ParallaxMap", props);occlusionStrength = FindProperty("_OcclusionStrength", props);occlusionMap = FindProperty("_OcclusionMap", props);emissionColorForRendering = FindProperty("_EmissionColor", props);emissionMap = FindProperty("_EmissionMap", props);detailMask = FindProperty("_DetailMask", props);detailAlbedoMap = FindProperty("_DetailAlbedoMap", props);detailNormalMapScale = FindProperty("_DetailNormalMapScale", props);detailNormalMap = FindProperty("_DetailNormalMap", props);uvSetSecondary = FindProperty("_UVSec", props);}public override void OnGUI(MaterialEditor materialEditor, MaterialProperty[] props){FindProperties(props); // MaterialProperties can be animated so we do not cache them but fetch them every event to ensure animated values are updated correctlym_MaterialEditor = materialEditor;Material material = materialEditor.target as Material;// Make sure that needed setup (ie keywords/renderqueue) are set up if we're switching some existing// material to a standard shader.// Do this before any GUI code has been issued to prevent layout issues in subsequent GUILayout statements (case 780071)if (m_FirstTimeApply){MaterialChanged(material, m_WorkflowMode);m_FirstTimeApply = false;}ShaderPropertiesGUI(material);}public void ShaderPropertiesGUI(Material material){// Use default labelWidthEditorGUIUtility.labelWidth = 0f;// Detect any changes to the materialEditorGUI.BeginChangeCheck();{BlendModePopup();// Primary propertiesGUILayout.Label(Styles.primaryMapsText, EditorStyles.boldLabel);DoAlbedoArea(material);DoSpecularMetallicArea();m_MaterialEditor.TexturePropertySingleLine(Styles.normalMapText, bumpMap, bumpMap.textureValue != null ? bumpScale : null);m_MaterialEditor.TexturePropertySingleLine(Styles.heightMapText, heightMap, heightMap.textureValue != null ? heigtMapScale : null);m_MaterialEditor.TexturePropertySingleLine(Styles.occlusionText, occlusionMap, occlusionMap.textureValue != null ? occlusionStrength : null);m_MaterialEditor.TexturePropertySingleLine(Styles.detailMaskText, detailMask);DoEmissionArea(material);EditorGUI.BeginChangeCheck();m_MaterialEditor.TextureScaleOffsetProperty(albedoMap);if (EditorGUI.EndChangeCheck())emissionMap.textureScaleAndOffset = albedoMap.textureScaleAndOffset; // Apply the main texture scale and offset to the emission texture as well, for Enlighten's sakeEditorGUILayout.Space();// Secondary propertiesGUILayout.Label(Styles.secondaryMapsText, EditorStyles.boldLabel);m_MaterialEditor.TexturePropertySingleLine(Styles.detailAlbedoText, detailAlbedoMap);m_MaterialEditor.TexturePropertySingleLine(Styles.detailNormalMapText, detailNormalMap, detailNormalMapScale);m_MaterialEditor.TextureScaleOffsetProperty(detailAlbedoMap);m_MaterialEditor.ShaderProperty(uvSetSecondary, Styles.uvSetLabel.text);// Third propertiesGUILayout.Label(Styles.forwardText, EditorStyles.boldLabel);if (highlights != null)m_MaterialEditor.ShaderProperty(highlights, Styles.highlightsText);if (reflections != null)m_MaterialEditor.ShaderProperty(reflections, Styles.reflectionsText);}if (EditorGUI.EndChangeCheck()){foreach (var obj in blendMode.targets)MaterialChanged((Material)obj, m_WorkflowMode);}EditorGUILayout.Space();GUILayout.Label(Styles.advancedText, EditorStyles.boldLabel);m_MaterialEditor.RenderQueueField();m_MaterialEditor.EnableInstancingField();}internal void DetermineWorkflow(MaterialProperty[] props){if (FindProperty("_SpecGlossMap", props, false) != null && FindProperty("_SpecColor", props, false) != null)m_WorkflowMode = WorkflowMode.Specular;else if (FindProperty("_MetallicGlossMap", props, false) != null && FindProperty("_Metallic", props, false) != null)m_WorkflowMode = WorkflowMode.Metallic;elsem_WorkflowMode = WorkflowMode.Dielectric;}public override void AssignNewShaderToMaterial(Material material, Shader oldShader, Shader newShader){// _Emission property is lost after assigning Standard shader to the material// thus transfer it before assigning the new shaderif (material.HasProperty("_Emission")){material.SetColor("_EmissionColor", material.GetColor("_Emission"));}base.AssignNewShaderToMaterial(material, oldShader, newShader);if (oldShader == null || !oldShader.name.Contains("Legacy Shaders/")){SetupMaterialWithBlendMode(material, (BlendMode)material.GetFloat("_Mode"));return;}BlendMode blendMode = BlendMode.Opaque;if (oldShader.name.Contains("/Transparent/Cutout/")){blendMode = BlendMode.Cutout;}else if (oldShader.name.Contains("/Transparent/")){// NOTE: legacy shaders did not provide physically based transparency// therefore Fade modeblendMode = BlendMode.Fade;}material.SetFloat("_Mode", (float)blendMode);DetermineWorkflow(MaterialEditor.GetMaterialProperties(new Material[] { material }));MaterialChanged(material, m_WorkflowMode);}void BlendModePopup(){EditorGUI.showMixedValue = blendMode.hasMixedValue;var mode = (BlendMode)blendMode.floatValue;EditorGUI.BeginChangeCheck();mode = (BlendMode)EditorGUILayout.Popup(Styles.renderingMode, (int)mode, Styles.blendNames);if (EditorGUI.EndChangeCheck()){m_MaterialEditor.RegisterPropertyChangeUndo("Rendering Mode");blendMode.floatValue = (float)mode;}EditorGUI.showMixedValue = false;}void DoAlbedoArea(Material material){m_MaterialEditor.TexturePropertySingleLine(Styles.albedoText, albedoMap, albedoColor);if (((BlendMode)material.GetFloat("_Mode") == BlendMode.Cutout)){m_MaterialEditor.ShaderProperty(alphaCutoff, Styles.alphaCutoffText.text, MaterialEditor.kMiniTextureFieldLabelIndentLevel + 1);}}void DoEmissionArea(Material material){// Emission for GI?if (m_MaterialEditor.EmissionEnabledProperty()){bool hadEmissionTexture = emissionMap.textureValue != null;// Texture and HDR color controlsm_MaterialEditor.TexturePropertyWithHDRColor(Styles.emissionText, emissionMap, emissionColorForRendering, m_ColorPickerHDRConfig, false);// If texture was assigned and color was black set color to whitefloat brightness = emissionColorForRendering.colorValue.maxColorComponent;if (emissionMap.textureValue != null && !hadEmissionTexture && brightness <= 0f)emissionColorForRendering.colorValue = Color.white;// change the GI flag and fix it up with emissive as black if necessarym_MaterialEditor.LightmapEmissionFlagsProperty(MaterialEditor.kMiniTextureFieldLabelIndentLevel, true);}}void DoSpecularMetallicArea(){bool hasGlossMap = false;if (m_WorkflowMode == WorkflowMode.Specular){hasGlossMap = specularMap.textureValue != null;m_MaterialEditor.TexturePropertySingleLine(Styles.specularMapText, specularMap, hasGlossMap ? null : specularColor);}else if (m_WorkflowMode == WorkflowMode.Metallic){hasGlossMap = metallicMap.textureValue != null;m_MaterialEditor.TexturePropertySingleLine(Styles.metallicMapText, metallicMap, hasGlossMap ? null : metallic);}bool showSmoothnessScale = hasGlossMap;if (smoothnessMapChannel != null){int smoothnessChannel = (int)smoothnessMapChannel.floatValue;if (smoothnessChannel == (int)SmoothnessMapChannel.AlbedoAlpha)showSmoothnessScale = true;}int indentation = 2; // align with labels of texture propertiesm_MaterialEditor.ShaderProperty(showSmoothnessScale ? smoothnessScale : smoothness, showSmoothnessScale ? Styles.smoothnessScaleText : Styles.smoothnessText, indentation);++indentation;if (smoothnessMapChannel != null)m_MaterialEditor.ShaderProperty(smoothnessMapChannel, Styles.smoothnessMapChannelText, indentation);}public static void SetupMaterialWithBlendMode(Material material, BlendMode blendMode){switch (blendMode){case BlendMode.Opaque: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("_ALPHATEST_ON");material.DisableKeyword("_ALPHABLEND_ON");material.DisableKeyword("_ALPHAPREMULTIPLY_ON");material.renderQueue = -1;break;case BlendMode.Cutout:material.SetOverrideTag("RenderType", "TransparentCutout");material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.One);material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.Zero);material.SetInt("_ZWrite", 1);material.EnableKeyword("_ALPHATEST_ON");material.DisableKeyword("_ALPHABLEND_ON");material.DisableKeyword("_ALPHAPREMULTIPLY_ON");material.renderQueue = (int)UnityEngine.Rendering.RenderQueue.AlphaTest;break;case BlendMode.Fade: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("_ALPHATEST_ON");material.EnableKeyword("_ALPHABLEND_ON");material.DisableKeyword("_ALPHAPREMULTIPLY_ON");material.renderQueue = (int)UnityEngine.Rendering.RenderQueue.Transparent;break;case BlendMode.Transparent: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.DisableKeyword("_ALPHATEST_ON");material.DisableKeyword("_ALPHABLEND_ON");material.EnableKeyword("_ALPHAPREMULTIPLY_ON");material.renderQueue = (int)UnityEngine.Rendering.RenderQueue.Transparent;break;}}static SmoothnessMapChannel GetSmoothnessMapChannel(Material material){int ch = (int)material.GetFloat("_SmoothnessTextureChannel");if (ch == (int)SmoothnessMapChannel.AlbedoAlpha)return SmoothnessMapChannel.AlbedoAlpha;elsereturn SmoothnessMapChannel.SpecularMetallicAlpha;}static void SetMaterialKeywords(Material material, WorkflowMode workflowMode){// Note: keywords must be based on Material value not on MaterialProperty due to multi-edit & material animation// (MaterialProperty value might come from renderer material property block)SetKeyword(material, "_NORMALMAP", material.GetTexture("_BumpMap") || material.GetTexture("_DetailNormalMap"));if (workflowMode == WorkflowMode.Specular)SetKeyword(material, "_SPECGLOSSMAP", material.GetTexture("_SpecGlossMap"));else if (workflowMode == WorkflowMode.Metallic)SetKeyword(material, "_METALLICGLOSSMAP", material.GetTexture("_MetallicGlossMap"));SetKeyword(material, "_PARALLAXMAP", material.GetTexture("_ParallaxMap"));SetKeyword(material, "_DETAIL_MULX2", material.GetTexture("_DetailAlbedoMap") || material.GetTexture("_DetailNormalMap"));// A material's GI flag internally keeps track of whether emission is enabled at all, it's enabled but has no effect// or is enabled and may be modified at runtime. This state depends on the values of the current flag and emissive color.// The fixup routine makes sure that the material is in the correct state if/when changes are made to the mode or color.MaterialEditor.FixupEmissiveFlag(material);bool shouldEmissionBeEnabled = (material.globalIlluminationFlags & MaterialGlobalIlluminationFlags.EmissiveIsBlack) == 0;SetKeyword(material, "_EMISSION", shouldEmissionBeEnabled);if (material.HasProperty("_SmoothnessTextureChannel")){SetKeyword(material, "_SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A", GetSmoothnessMapChannel(material) == SmoothnessMapChannel.AlbedoAlpha);}}static void MaterialChanged(Material material, WorkflowMode workflowMode){SetupMaterialWithBlendMode(material, (BlendMode)material.GetFloat("_Mode"));SetMaterialKeywords(material, workflowMode);}static void SetKeyword(Material m, string keyword, bool state){if (state)m.EnableKeyword(keyword);elsem.DisableKeyword(keyword);}}
} // namespace UnityEditor

定位到上述脚本的393行(不同版本的脚本可能不太一样,看具体情况),即是设置自发光是否开启的部分。

其实就是使用material的EnableKeyword和DisableKeyword来控制_EMISSION属性的开关,知道原理之后写代码就简单了。

using UnityEngine;/// <summary>
/// 指示灯.
/// </summary>
public class HightLED : MonoBehaviour
{private Material mat;private void Awake(){mat = GetComponent<MeshRenderer>().material;}private void Update(){if (Input.GetKeyDown(KeyCode.F1)){SetEmission(mat, true);}if (Input.GetKeyDown(KeyCode.F2)){SetEmission(mat, false);}}private void SetEmission(Material mat, bool emissionOn){if (emissionOn){mat.EnableKeyword("_EMISSION");}else{mat.DisableKeyword("_EMISSION");}}
}

4.建议测试时把场景中内置的天空盒给删除掉,内置天空盒给的光太多,看不出效果。具体步骤见下图。


源码上传到GitHub了,见03.HightLight场景。

Unity3D实现指示灯亮灭效果相关推荐

  1. ses控制硬盘指示灯亮灭

    前言 某块硬盘出现故障了,以/dev/sdal为例.虽然在操作系统里面可以看到/dev/sdal是无法读取故障了, 但去了机房现场,发现硬盘的指示灯没有变成红色,并且服务器上面插着数十块硬盘. 那么如 ...

  2. 阿里云IoT:控制掌控板板载灯亮灭

    文章目录 准备工作 1.注册账号并登录阿里云IoT平台 2.进行实名验证 3.开通物联网平台 创建产品 1.新建一个名为"Light"的产品 2.进行功能定义 添加设备 开发手机A ...

  3. 6-51单片机ESP8266学习-AT指令(8266TCP服务器--做自己的AndroidTCP客户端发信息给单片机控制小灯的亮灭)...

    http://www.cnblogs.com/yangfengwu/p/8776712.html 先把源码和资料链接放到这里 链接: https://pan.baidu.com/s/1jpHZjW_7 ...

  4. 【Proteus仿真8086】简单IO接口实验——读取开关状态控制灯的亮灭

    本次实验内容来自于何宏老师<微机原理与接口技术 基于Proteus仿真的8086微机系统设计及应用>的12.1节基本I/O口应用,略有改动 用245读取开关状态,然后用373控制开关的亮灭 ...

  5. Android 知识点 109 —— Android7.0 PowerManagerService 之亮灭屏

    原文地址: https://www.cnblogs.com/dyufei/p/8017604.html 写的太好了,粘过来! 本篇从按下power按键后,按键事件从InputManagerServic ...

  6. FPGA——输入原理图实现按键控制发光二极管的亮灭

    文章目录 前言 一.FPGA的设计流程 二.按键控制发光二极管的亮灭的过程 (一)创建工程 (二)绘制原理图 (三)编译 (四)分配引脚 (五)仿真与时序分析 (六)配置FPGA (七)下载结果 总结 ...

  7. Android Studio设计APP实现与51单片机通过WIFI模块(ESP8266-01S)通讯控制LED灯亮灭的设计源码【详解】

    目录 一.前言 二.效果展示 1.APP界面展示 2.C51硬件展示 三.Android Studio APP源代码 1.AndroidManifest.xml 1.请求联网: 2.开放明文传输: 2 ...

  8. ZYNQ学习笔记(五)---按键控制LED灯亮灭实验

    这个实验其实很早就做了,但是由于这段时间自己一直在忙一些其他的事所以没有及时更新.今天抽出个空来更新一下.本次实验是关于按键控制LED亮灭.其中涉及到的内容有计数器.按键消抖以及一些简单的逻辑. 1. ...

  9. STM32c8t6串口+蓝牙控制PC13亮灭

    Hello,大家好,这是我第一次来CSDN上写,想像CSDN里的前辈一样,对自己的知识做一种记录和总结,并且也希望里面内容有能帮助到大家的. 目录 一.模块介绍 二.程序调试 1. USART1 2. ...

最新文章

  1. Java集合框架综述,这篇让你吃透!
  2. webpack 搭建rect项目
  3. SylixOS与硬件设备连接问题——硬件设备串口、网口连接问题
  4. 传输文件过程中遇到异常被中断
  5. android staido 断点遇到的坑
  6. 数据结构Stack:关系以及方法
  7. 使用Jest操作ElasticSearch 报错:No time zone indicator问题的解决方案
  8. python修改数据库_python mysql修改数据库数据库
  9. Jenkins启动时提示:Starting Jenkins Jenkins requires Java8 or later, but you are running 1.7.0
  10. getopts命令行参数处理
  11. Python IDE 详细攻略,拿来吧你~
  12. KR C 传统C语言的函数定义
  13. 如何让Mosquitto动态加载配置文件
  14. Openwrt笔记-1-校园网连接
  15. linux免密码登录
  16. ADO方法访问数据库的封装接口
  17. 2021年11月视频行业用户洞察
  18. 《智能商业》由阿里巴巴学术委员会主席、前总参谋长曾鸣亲自编写,值得一读!
  19. html css特效,15个超酷的CSS3代码特效展示
  20. java兔子字符画,兔子的字符画

热门文章

  1. 一波三折的云计算HCIE之旅
  2. Android 使用NDK开发中,遇到memset,memcpy, malloc函数错误
  3. 阿里云开源业界首个面向NLP场景深度迁移学习框架
  4. 全球的生活服务型机器人产业发展得比较迅猛
  5. c语言结构体定义坐标,C/C++知识点之c语言结构体定义的几种形式
  6. MySQL 服务正在启动 MySQL 服务无法启动解决办法
  7. 改善交互动效设计 实例
  8. 做职业监理师(八)——怎样规范应用《监理通知书》
  9. 音乐考试统考分数计算机,音乐艺考分数怎么算 音乐艺考分数比例
  10. java-htttp-远程访问之RestTemplate,json