我使用的版本为2019.4.12(LTS)版本,项目是HDRP项目。
边角压暗效果的触发,可以按钮触发,也可以按键触发,按钮触发直接调用ButtonEvent()方法就好了。两种方式稍微有点差距,但不大。
首先先在项目里新建后处理的配置文件,方法如下:
然后随便创建一个空物体,挂上脚本DynamicVignette
脚本如下:
using System.Collections;
using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.Rendering.HighDefinition;
/*
*
* Writer:June
*
* Date: 2020.10.14
*
* Function:动态边角压暗效果
*
* Remarks:
*
*/
/// <summary>
/// 挂载当前脚本的GameObject必须确保有Volume组件
/// </summary>
[RequireComponent(typeof(Volume))]
public class DynamicVignette : MonoBehaviour
{
/// <summary>
/// 后处理体积容器
/// </summary>
private Volume volume;
/// <summary>
/// 对应要修改的效果————>边角压暗效果
/// </summary>
private Vignette vignette;
/// <summary>
/// 是否成功获取边角压暗属性
/// </summary>
public bool IsGetAttribute { get; private set; }
/// <summary>
/// 动画播放需要的时间
/// </summary>
public float animtionTime;
/// <summary>
/// 强度范围
/// </summary>
[Range(0.1f, 1)]
public float vignetteIntensity = 0.1f;
/// <summary>
/// 动画开关
/// </summary>
private bool isPlay = false;
/// <summary>
/// 计时器
/// </summary>
private float timer = 0;
/// <summary>
/// 每帧更新的强度总和(用于对边角压暗强度的赋值,并且每帧更新)
/// </summary>
private float frameIntensity = 0;
/// <summary>
/// 帧率
/// </summary>
[Range(10, 60)]
public float frameRate = 60;
private void Start()
{
//获取引用
volume = GetComponent<Volume>();
//从配置文件或配置表中获取属性 TryGet方法返回的是bool类型的
IsGetAttribute = volume.profile.TryGet(out vignette);
}
private void Update()
{
if (Input.GetKeyDown(KeyCode.A))
{
//使用协程
StartCoroutine(VignetteEffect());
}
}
//经过测试,每秒执行51次,Update函数每秒执行次数不一定
private void FixedUpdate()
{
//确保获取到了属性
if (!IsGetAttribute) return;
if (isPlay)
{
timer += Time.deltaTime;
VignetteEffect(timer);
}
}
/// <summary>
/// 按钮触发
/// </summary>
public void ButtonEvent()
{
isPlay = true;
}
/// <summary>
/// 边角压暗效果
/// tips:注意intensity不可以直接赋值,intensity的类型不是float
/// </summary>
private void VignetteEffect(float currentTime)
{
//判断时间
if (currentTime >= animtionTime / 2f)
{
//用 总时间的一半 * 帧率 = 在这段时间要更新的帧数,再用 规定的强度 / 总帧数 = 每帧更新的强度
frameIntensity -= vignetteIntensity / (51 * animtionTime / 2f);
vignette.intensity.value = frameIntensity;
}
else
{
frameIntensity += vignetteIntensity / (51 * animtionTime / 2f);
vignette.intensity.value = frameIntensity;
}
//播放完成
if (currentTime >= animtionTime)
{
isPlay = false;
timer = 0;
frameIntensity = 0;
}
}
/// <summary>
/// 边角压暗效果协程
/// </summary>
/// <returns></returns>
IEnumerator VignetteEffect()
{
//从0->目标强度
for (float i = 0; i <= vignetteIntensity; i+= vignetteIntensity / (frameRate * animtionTime / 2f))
{
vignette.intensity.value = i;
//每0.02秒更新一帧
yield return new WaitForSeconds(0.02f);
}
//从目标强度->0
for (float i = vignetteIntensity; i >= 0; i -= vignetteIntensity / (frameRate * animtionTime / 2f))
{
vignette.intensity.value = i;
yield return new WaitForSeconds(0.02f);
}
}
}
最后的效果:
2020.11.09更新
做了一些处理,不是通过时间来限制,而是用变化速度,以及一些小优化,外部只要直接调用TriggerEffect(),就有边角压暗的渐变效果(可以用来做被敌人攻击的后,屏幕效果,不过有点大材小用了,哈哈,这里我只是做一个引申!)
using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.Rendering.HighDefinition;
/*
*
* Writer:June
*
* Date: 2020.11.09
*
* Function:控制后处理效果之边角压暗效果
*
* Remarks:
*
*/
[RequireComponent(typeof(Volume))]
public class ControlPP_Vignette : MonoBehaviour
{
/// <summary>
/// 后期处理容器
/// </summary>
private Volume volume;
/// <summary>
/// 边角压暗效果
/// </summary>
private Vignette vignette;
/// <summary>
/// 是否成功获取边角压暗属性
/// </summary>
public bool IsGetAttribute { get; private set; }
/// <summary>
/// 显示/隐藏边角压暗
/// </summary>
private bool IsFadeIn, IsFadeOut;
/// <summary>
/// 压暗的变化速度
/// </summary>
[Header("压暗效果的变化速度"),Range(0.5f,5),SerializeField]
private float fadeSpeed = 1f;
/// <summary>
/// 压暗强度最大值
/// </summary>
[Header("压暗强度最大值"), Range(0, 1),SerializeField]
private float effectMax = 0.6f;
/// <summary>
/// 默认初始化颜色
/// </summary>
public Color defaultColor;
private void Start()
{
//获取引用
volume = GetComponent<Volume>();
//默认关闭
IsFadeIn = false;
//从配置文件或配置表中获取属性 TryGet方法返回的是bool类型的
IsGetAttribute = volume.profile.TryGet(out vignette);
//如果没有获取到边角压暗效果,则创建边角压暗效果
if (!IsGetAttribute) CreatVignetteEffect(defaultColor);
}
private void Update()
{
if (IsFadeIn)
{
vignette.intensity.value += fadeSpeed * Time.deltaTime;
//判断是否达到目标,到达后设置为false
IsFadeIn = vignette.intensity.value < effectMax;
IsFadeOut = !IsFadeIn;
}
if (IsFadeOut)
{
vignette.intensity.value -= fadeSpeed * Time.deltaTime;
IsFadeOut = vignette.intensity.value < effectMax;
}
}
/// <summary>
/// 触发边角压暗效果(提供给外部调用)
/// </summary>
public void TriggerEffect()
{
//先判断是否获取得到了边角压暗
if (IsGetAttribute) IsFadeIn = true;
}
/// <summary>
/// 创建边角压暗效果
/// </summary>
/// <param name="color">初始颜色</param>
private void CreatVignetteEffect(Color color)
{
//将边角压暗效果添加到配置文件中 ture:将所有属性激活
vignette = volume.profile.Add<Vignette>(true);
//初始化颜色
vignette.color.value = color;
//初始化强度
vignette.intensity.value = 0;
//标记为获取到边角压暗
IsGetAttribute = true;
}
}