Unity工具——LightTransition(光照过渡)

需求描述

        在游戏中,开发者为了让玩家更直接地看到待拾取的物品从而为其添加一种闪烁效果,或者模拟现实中闪烁的灯光效果,我能够想到的一种方案则是通过控制光照强度来实现,那么本篇文章我们就尝试通过这个方案来实现一下,看看是否能够满足这类需求,这也能够作为我们个人资源库的一部分,以后如果在开发中有这方面需求,就可以直接把这个方案搬过来用,虽然这可能只是一个小小的功能,但这是一个积少成多的过程,只要我们能够完整地实现并使之通过测试,那么就算是一种成功,也能够从中获得收获。

功能描述

        如果大家了解过LightLight2D组件,那么就应该知道其中的intensity属性用于控制光照强度,本质上闪烁就是通过改变光照强度的值来控制的,从暗到明,则对应intensity的值从小到大。        

        首先我们需要两个属性——光照强度起始值beginValue光照强度最终值endValue,还有从beginValue到endValue的光照强度变化的步长值stepValue,同时还要确定等待时间的属性timeSpan。为了使得这个组件应用更广泛,我们不公开beginValue和endValue,而是让使用者明确光照强度的最小值minValue以及光照强度最大值maxValue,所以beginValue既可以是minValue也可以是maxValue,这取决于使用者的需求。

        其次就是需要明确从beginValue到endValue的过渡方式了,我首先能够想到的是是否需要循环闪烁,假定属性Loop用于明确是否循环闪烁,如果不循环闪烁,那么只要从beginValue过渡到endValue就结束,若需要循环闪烁则需要明确循环的方式,如果每次循环都是从beginValue过渡到endValue则可以假定这种方式叫BeginToEnd,除此之外还可以是先从beginValue过渡到endValue然后再过渡到beginValue,类似一个钟摆一样,假定这种方式叫Pendulum

        最后我们还可以规定beginValue的取值,我们规定它要么是minValue,要么是maxValue,只要确定了beginValue,就可以确定endValue,所以我们假定属性beginValueType用于明确光照强度起始值的类型。

属性解释
LightUnity的Light组件
Light2DUniversal RP中的Light2D组件
intensity

Light/Light2D组件的光照强度属性

beginValue光照强度起始值
endValue光照强度最终值
stepValue光照强度变化的步长值
timeSpan光照强度变化的时间间隔
minValue光照强度的最小值
maxValue光照强度的最大值
Loop是否循环闪烁
BeginToEnd每次循环都是从beginValue过渡到endValue
Pendulum先从beginValue过渡到endValue然后再过渡到beginValue,类似一个钟摆
beginValueType光照强度起始值的类型

代码展示(C#)

CommonLightTransition.cs

using System.Collections;
using UnityEngine;namespace Tools
{public class CommonLightTransition : MonoBehaviour{[Header("必要属性")][Tooltip("光照强度变化平均值,默认值为0.1(值>0)")][SerializeField] private float IntensityStepValue = 0.1f;[Tooltip("光照强度最小值,默认值为1(值属于[0,IntensityMaxValue))")][SerializeField] private float IntensityMinValue = 1;[Tooltip("光照强度最大值,默认值为2(值>IntensityMinValue)")][SerializeField] private float IntensityMaxValue = 2;[Tooltip("过渡时间间隔,默认值为0.05,单位s(值>0)")][SerializeField] private float TransitionTimeSpan = 0.05f;[Tooltip("是否开启光照过渡循环,默认值为true")][SerializeField] private bool Loop = true;[Tooltip("光照过渡循环方式,需要勾选Loop该选项才有效,BeginToEnd是每次循环从光照过渡起始值开始,Pendulum是从光照过渡起始值至光照过渡最终值再过渡至光照过渡起始值(钟摆式过渡)")][SerializeField] private LoopMode TheLoopMode;[Tooltip("光照过渡起始值类型,Min代表起始值从IntensityMinValue开始,Max同理")][SerializeField] private BeginValueType TransitionBeginValueType;protected bool toMax;protected bool lockUnLoopTransition;protected int index;protected bool _isInit { get => isInit; }protected float[] _changedValues { get => changedValues; }protected BeginValueType _transitionBeginValueType { get => TransitionBeginValueType; }protected bool _loop { get => Loop; }protected LoopMode _loopMode { get => TheLoopMode; }protected float _intensityMinValue { get => IntensityMinValue; }protected float _intensityMaxValue { get => IntensityMaxValue; }private bool isInit, endTransition;private float[] changedValues;private IEnumerator coroutine;/// <summary>/// 启动过渡/// </summary>public void StartTransition(){if (isInit && endTransition){StartCoroutine(coroutine);endTransition = false;}}/// <summary>/// 停止过渡/// </summary>public void StopTransition(){if (isInit && !endTransition){StopCoroutine(coroutine);endTransition = true;}}/// <summary>/// 初始化游戏对象相关组件/// <para>返回值:初始化组件成功则返回true,否则返回false</para>/// </summary>protected virtual bool InitComponents() { return false; }/// <summary>/// 光照过渡类型处理/// </summary>protected virtual void TransitionTypeDeal() { }/// <summary>/// 非循环光照过渡/// </summary>protected virtual void UnLoopLightTransition() { }/// <summary>/// 循环光照过渡/// </summary>protected virtual void LoopLightTransition() { }/// <summary>/// 组件检测控制台提示方法/// <para>声明:该方法仅在Unity Editor模式下且当Inspector面板中组件属性发生更改时执行</para>/// </summary>protected virtual void ComponentLog() { }/// <summary>/// 光照过渡起始值类型/// </summary>protected enum BeginValueType{Min, Max}/// <summary>/// 循环光照过渡方式/// </summary>protected enum LoopMode{BeginToEnd, Pendulum}private void Start(){isInit = InitComponents() && InitParameters();}//初始化游戏对象相关参数private bool InitParameters(){if (IntensityStepValue <= 0 || IntensityMinValue < 0 || IntensityMaxValue <= 0) return false;if (IntensityMinValue >= IntensityMaxValue) return false;if (TransitionTimeSpan <= 0) return false;changedValues = NumberRange.FloatRange(IntensityMinValue, IntensityMaxValue, IntensityStepValue, true);if (changedValues == null && changedValues.Length == 0) return false;TransitionTypeDeal();coroutine = UnLoopTransition();if (Loop){lockUnLoopTransition = true;coroutine = LoopTransition();}endTransition = true;return true;}private IEnumerator LoopTransition(){while (true){LoopLightTransition();yield return new WaitForSeconds(TransitionTimeSpan);}}private IEnumerator UnLoopTransition(){while (!lockUnLoopTransition){UnLoopLightTransition();yield return new WaitForSeconds(TransitionTimeSpan);}endTransition = true;}#if UNITY_EDITORprivate void OnValidate(){ComponentLog();}
#endif}
}

LightTransition2D.cs 

using UnityEngine.Experimental.Rendering.Universal;
using UnityEngine;namespace Tools
{public class LightTransition2D : CommonLightTransition{[Header("必要组件(需要下载扩展包:Universal RP)")][Tooltip("Light2D组件")][SerializeField] private Light2D Light2D;private bool isLight2DLog;//初始化游戏对象相关组件protected sealed override bool InitComponents(){if (Light2D == null) return false;return true;}//光照过渡类型处理protected sealed override void TransitionTypeDeal(){if (_transitionBeginValueType == BeginValueType.Min){Light2D.intensity = _intensityMinValue;index = 0;toMax = true;}else{Light2D.intensity = _intensityMaxValue;index = _changedValues.Length - 1;toMax = false;}}//非循环光照过渡protected sealed override void UnLoopLightTransition(){if (_isInit && !lockUnLoopTransition){if (_transitionBeginValueType == BeginValueType.Min){if (index >= _changedValues.Length){lockUnLoopTransition = true;return;}Light2D.intensity = _changedValues[index++];}else{if (index < 0){lockUnLoopTransition = true;return;}Light2D.intensity = _changedValues[index--];}}}//循环光照过渡protected sealed override void LoopLightTransition(){if (_isInit && _loop){if (_loopMode == LoopMode.Pendulum){if (index <= 0) toMax = true;else if (index >= _changedValues.Length - 1) toMax = false;}else if (index < 0 || index > _changedValues.Length - 1) TransitionTypeDeal();if (toMax) Light2D.intensity = _changedValues[index++];else Light2D.intensity = _changedValues[index--];}}//组件检测控制台提示方法protected sealed override void ComponentLog(){if (Light2D == null){if (!isLight2DLog){Debug.LogWarning("The component \"<color=orange><b>Light2D</b></color>\" is null.");isLight2DLog = true;}}else isLight2DLog = false;}}
}

LightTransition.cs 

using UnityEngine;namespace Tools
{public class LightTransition : CommonLightTransition{[Header("必要组件")][Tooltip("Light组件")][SerializeField] private Light Light;private bool isLightLog;//初始化游戏对象相关组件protected sealed override bool InitComponents(){if (Light == null) return false;return true;}//光照过渡类型处理protected sealed override void TransitionTypeDeal(){if (_transitionBeginValueType == BeginValueType.Min){Light.intensity = _intensityMinValue;index = 0;toMax = true;}else{Light.intensity = _intensityMaxValue;index = _changedValues.Length - 1;toMax = false;}}//非循环光照过渡protected sealed override void UnLoopLightTransition(){if (_isInit && !lockUnLoopTransition){if (_transitionBeginValueType == BeginValueType.Min){if (index >= _changedValues.Length){lockUnLoopTransition = true;return;}Light.intensity = _changedValues[index++];}else{if (index < 0){lockUnLoopTransition = true;return;}Light.intensity = _changedValues[index--];}}}//循环光照过渡protected sealed override void LoopLightTransition(){if (_isInit && _loop){if (_loopMode == LoopMode.Pendulum){if (index <= 0) toMax = true;else if (index >= _changedValues.Length - 1) toMax = false;}else if (index < 0 || index > _changedValues.Length - 1) TransitionTypeDeal();if (toMax) Light.intensity = _changedValues[index++];else Light.intensity = _changedValues[index--];}}//组件检测控制台提示方法protected sealed override void ComponentLog(){if (Light == null){if (!isLightLog){Debug.LogWarning("The component \"<color=orange><b>Light</b></color>\" is null.");isLightLog = true;}}else isLightLog = false;}}
}

NumberRange.cs 

using System.Collections.Generic;
using System.Linq;namespace Tools
{/// <summary>/// 数值范围数组工具类/// </summary>public static class NumberRange{/// <summary>/// 获取指定范围内指定步长的Float数值数组/// <para>p_start:起始值</para>/// <para>p_end:终点值</para>/// <para>p_step:步长值</para>/// <para>[ContainsEnd]:是否包括终点值,默认为false</para>/// <para>返回值:Float[]</para>/// </summary>public static float[] FloatRange(float p_start, float p_end, float p_step, bool ContainsEnd = false){if (!ContainsEnd) return DoFloatRange(p_start, p_end, p_step).ToArray();else{List<float> result = DoFloatRange(p_start, p_end, p_step).ToList();result.Add(p_end);return result.ToArray();}}static IEnumerable<float> DoFloatRange(float p_start, float p_end, float p_step){for (float i = p_start; i <= p_end; i += p_step){yield return i;}}}
}

界面展示

LightTransition2D

LightTransition

部分演示效果

LightTransition2D组件的简单演示效果

LightTransition2D - Demo

资源下载

GitHub_LightTransition     百度网盘

 如果这篇文章对你有帮助,请给作者点个赞吧!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/138467.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

什么是Vue的Vetur插件?它有哪些功能

引言 在现代前端开发中&#xff0c;Vue.js已经成为了一个备受欢迎的JavaScript框架。随着Vue.js的流行&#xff0c;开发人员需要强大的工具来提高他们的生产力和Vue.js项目的质量。Vetur插件是一个为Vue.js开发者提供的强大工具&#xff0c;它不仅提供了丰富的功能&#xff0c…

vue框架实现表情打分效果

本来今天要实现这个功能 但是在网上查了一下 就csdn上有一个符合要求的 但是他竟然收费,痛心疾首啊 太伤白嫖党的心的 所以我手写了一个这个类似功能的代码 希望能帮到有这个需求的同学们 技术栈是VUE3 用其他技术栈的也可以看 因为逻辑很简单都一样的 // 问卷的虚拟数据 con…

前端框架vBean admin

文章目录 引言I 数据库表设计1.1 用户表1.2 角色表1.3 菜单表II 接口引言 文档:https://doc.vvbin.cn/guide/introduction.html http://doc.vvbin.cn 仓库:https://github.com/vbenjs/vue-vben-admin git clone https://github.com/vbenjs/vue-vben-admin-doc 在线体验demo:…

步步为营,如何将GOlang引用库的安全漏洞修干净

文章目录 引场景构建第一步、直接引用的第三方库升级修复策略1.确认是否为直接引用的第三方库2.找到需要升级的版本是否为release版本 第二步、间接引用的第三方库升级修复策略那么问题来了&#xff0c;我们这么间接引用库的对应的直接引用库是哪个呢&#xff1f; &#xff08;…

Hadoop NameNode执行命令工作流程

Hadoop NameNode执行命令工作流程 客户端API或者CLI与NameNode的交互命令数据的格式(1) 预处理流程(2) 创建NameNode与NameNodePrcServer流程(3) HDFS API以及CLI的命令到NameNode的工作执行流程(4) 执行命令的参数流动 客户端API或者CLI与NameNode的交互命令数据的格式 hadoop…

Apache 原生 Hadoop 运维命令

Hadoop 1、检查原生hadoop和压缩库是否可用 hadoop checknative2、打印hadoop环境的配置路径 hadoop classpathHDFS 1、查看hdfs文件系统的状态 hdfs dfsadmin -report2、获取安全模式的状态 hdfs dfsadmin -safemode get安全模式下只可进行读操作 3、文件系统健康检查 …

LeetCode_拓扑排序_困难_2603.收集树中金币

目录 1.题目2.思路3.代码实现&#xff08;Java&#xff09; 1.题目 给你一个 n 个节点的无向无根树&#xff0c;节点编号从 0 到 n - 1 。给你整数 n 和一个长度为 n - 1 的二维整数数组 edges &#xff0c;其中 edges[i] [ai, bi] 表示树中节点 ai 和 bi 之间有一条边。再给…

10分钟设置免费海外远程桌面

前言 本教程将向您介绍如何使用 Amazon Lightsail 服务的免费套餐轻松搭建属于您的远程桌面。依托于 Amazon 全球可用区&#xff0c;您可以在世界各地搭建符合您配置需求的远程桌面。 本教程需要先拥有亚马逊云科技海外账户。现在注册亚马逊云科技账户可以享受12个月免费套餐…

《向量数据库指南》——文心大模型+Milvus向量数据库搭建AI原生应用

亲爱的科技探险家们和代码魔法师们: 未来的钟声已经敲响,预示着一场极度炫酷的虚拟现实游戏即将展开。从初期简单的智能识别,到设计师级别的图纸设计,生成式AI技术(Generative AI)以其独特理念和创新模式重塑了传统内容生产效率和交互模式,在无数领域展现着非凡的才华。…

清易低功耗智能雨量监测站概述

一、低功耗智能雨量监测站概述产品概述 低功耗智能雨量监测站基于智能传感、无线通信、智能处理与智能控制等物联网技术的开发&#xff0c;利用智能传感技术&#xff0c;通过传感器测量降雨量&#xff0c;并使用物联网进行传输。无需专门的通信线路&#xff0c;在联网的状态下…

简单的手机电脑无线传输方案@固定android生成ftp的IP地址(android@windows)

文章目录 abstractwindows浏览android文件环境准备客户端软件无线网络链接步骤其他方法 手机浏览电脑文件公网局域网everythingpython http.server 高级:固定android设备IP准备检查模块是否生效 windows 访问ftp服务器快捷方式命令行方式双击启动方式普通快捷方式映射新的网络位…

zabbix网络管理安装教程

安装&#xff1a; apt install zabbix-server-mysql zabbix-frontend-php zabbix-nginx-conf zabbix-sql-scripts zabbix-agent 参考资源&#xff1a; 官网&#xff1a; 下载&#xff1a; 其它&#xff1a; 常用指令&#xff1a; 目标与应用价值&#xff1a; 部署难点&#…

【php经典算法】冒泡排序,冒泡排序原理,冒泡排序执行逻辑,执行过程,执行结果 代码

冒泡排序原理 每次比较两个相邻的元素&#xff0c;将较大的元素交换至右端 冒泡排序执行过程输出效果 冒泡排序实现思路 每次冒泡排序操作都会将相邻的两个元素进行比较&#xff0c;看是否满足大小关系要求&#xff0c;如果不满足&#xff0c;就交换这两个相邻元素的次序&…

在已知的二维坐标里找到最接近的点

一、业务场景 最近在研发的项目&#xff0c;在做可视化层&#xff0c;在全球地图上&#xff0c;对我们的国家的陆地地图经纬度按照步长为1的间隔做了二维处理。在得到一组整数的点位信息后&#xff0c;需要将我们已有的数据库数据(业务项目)按照地址的经纬度&#xff0c;映射到…

GUN、MIT、Apache、BSD、MPL各种开源协议介绍和区别

文章目录 目前主流的开源协议GNU通用公共许可证&#xff08;GNU General Public License&#xff0c;GPL&#xff09;MIT许可证Apache许可证BSD许可证MPL Mozilla公共许可证&#xff08;Mozilla Public License&#xff0c;MPL&#xff09; 各种主流开源协议的区别GNU通用公共许…

玩转Nginx

Nginx是什么 Nginx&#xff08;engine x&#xff09;是一款的Web服务器、反向代理服务器&#xff0c;能够实现前端Web应用的部署、请求反向代理及负载均衡处理等功能。 特点 轻量&#xff0c;占用内存少高可靠高并发、高性能可扩展性好支持热部署BSD许可证(开源、可修改再发…

使用FFmpeg+ubuntu系统转化flac无损音频为mp3

功能需求如上题,我们来具体的操作一下: 1.先在ubuntu上面安装FFmpeg:sudo apt install ffmpeg 2.进入有flac音频文件的目录使用下述命令: ffmpeg -i test.FLAC -c:a libmp3lame -q:a 2 output.mp3 3.如果没有什么意外的话,你就能看到你的文件夹里面已经有转化好的mp3文件了 批…

Python —— excel文件操作(超详细)

背景 很多公司还是用excel去管理测试用例的&#xff0c;所以为了减少重复繁琐的导出导出工作&#xff0c;学会如何用代码操作excel表格很实用~ 1、读取excel文件基本步骤 1、操作excel的一些库 1、xlrd&#xff1a;读取库&#xff0c;xlwt&#xff1a;写入&#xff0c;现在…

Golang Linux 安装与环境变量配置

下载 Go 二进制包 wget https://dl.google.com/go/go1.21.1.linux-amd64.tar.gz 解压文件并将其移至 /usr/local 目录 sudo tar -C /usr/local -xzf go1.20.1.linux-amd64.tar.gz -C 选项解压文件到 /usr/local 目录&#xff0c;查看 /usr/local/go 目录的内容 将 Go 二进…

token登录的实现

token登录的实现 我这种token只是简单的实现token&#xff0c;就是后端利用UUID 生成简单随机码&#xff0c;利用随机码作为在Redis中的键&#xff0c;然后存储的用户信息作为值&#xff0c;在每次合理请求的时候对token的有效时间进行刷新&#xff08;利用拦截器&#xff09;&…