当前位置: 首页 > news >正文

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.lryc.cn/news/166616.html

相关文章:

  • 【深度学习】 Python 和 NumPy 系列教程(十四):Matplotlib详解:1、2d绘图(下):箱线图、热力图、面积图、等高线图、极坐标图
  • IMU+摄像头实现无标记运动捕捉
  • 前后端分离,JSON数据如何交互
  • docker中已创建容器的修改方法
  • uniapp中video播放视频上按钮没显示的问题
  • docker学习:dockerfile和docker-compose
  • Pycharm 配置python项目本地运行环境
  • DevEco Studio中如何设置HarmonyOS/OpenHarmony应用开发
  • Matlab图像处理-三原色
  • QLExpress代码解读,运行原理解析
  • M1 Mac创建虚拟环境遇到的问题
  • flutter 与H5交互
  • 【Java 基础篇】Java类型通配符:解密泛型的神秘面纱
  • 《极客时间:如何成为学习高手》【方法论】
  • 如何处理ChatGPT在文本生成中的语法错误和不合理性?
  • GitHub常用命令
  • 【Linux学习笔记】 - 常用指令学习及其验证(上)
  • 火山引擎边缘云助力智能科技赋予生活更多新意
  • 【无标题】CTreeCtrl更改-/+展开按钮颜色
  • 【深度学习】 Python 和 NumPy 系列教程(十九):Matplotlib详解:2、3d绘图类型(5)3D等高线图(3D Contour Plot)
  • Java ZGC 算法调优
  • 【海思SS626 | 开发环境】编译整个SDK全过程以及问题汇总
  • 83 # 静态服务中间件 koa-static 的使用以及实现
  • 带讲解的自行车租赁系统,可做毕设/课设
  • mysql指令
  • 【C语言】每日一题(半月斩)——day2
  • 电脑如何查看代理服务器IP?
  • 【C++11】{}初始化、std::initializer_list、decltype、STL新增容器
  • 【FPGA项目】进阶版沙盘演练——报文收发(报文处理、CDC、CRC)
  • 【程序员装机】自定义Edge浏览器用户目录