Unity_物体发光闪烁

小功能丨Unity中利用材质自发光实现物体闪烁效果

本文基于VDer的文章《Unity中利用材质自发光实现物体闪烁效果》延伸开发

在实现了具有一个Material的物体闪烁发光之后,延伸开发了具有多个Material的自闪烁效果,感谢VDer的技术分享!

使用方法:直接将该脚本挂到物体上,AutoStart为自动闪烁。具体功能看脚本。

 

2019.12.21更新:

若物体不闪烁,参照ViveFocus博客:链接

2019.05.21更新:

该脚本所挂物体Start时现在可以处于关闭状态啦(原先初始化时必须激活,否则不闪烁)

2018.11.28更新:

增加当前是否发光状态监测:isGlinting

 

Code:

using System.Collections;
using UnityEngine;
 
public class Skode_Glinting : MonoBehaviour
{
    /// <summary>
    /// 闪烁颜色
    /// </summary>
    public Color color = new Color(61 / 255f, 226 / 255f, 131 / 255, 1);
 
    /// <summary>
    /// 最低发光亮度,取值范围[0,1],需小于最高发光亮度。
    /// </summary>
    [Tooltip("最低发光亮度,取值范围[0,1],需小于最高发光亮度。")]
    [Range(0.0f, 1.0f)]
    public float minBrightness = 0.0f;
 
    /// <summary>
    /// 最高发光亮度,取值范围[0,1],需大于最低发光亮度。
    /// </summary>
    [Tooltip("最高发光亮度,取值范围[0,1],需大于最低发光亮度。")]
    [Range(0.0f, 1)]
    public float maxBrightness = 0.5f;
 
    /// <summary>
    /// 闪烁频率,取值范围[0.2,30.0]。
    /// </summary>
    [Tooltip("闪烁频率,取值范围[0.2,30.0]。")]
    [Range(0.2f, 30.0f)]
    public float rate = 1;
 
    //是否闪烁
    [HideInInspector]
    public bool isGlinting = false;
 
 
    [Tooltip("勾选此项则启动时自动开始闪烁")]
    [SerializeField]
    private bool _autoStart = false;
 
    private float _h, _s, _v;           // 色调,饱和度,亮度
    private float _deltaBrightness;     // 最低最高亮度差
    private Renderer _renderer;
 
    //private Material _material;
    private Material[] _materials;
 
    private readonly string _keyword = "_EMISSION";
    private readonly string _colorName = "_EmissionColor";
 
    private Coroutine _glinting;
 
    private void OnEnable()
    {
        _renderer = gameObject.GetComponent<Renderer>();
 
        //_material = _renderer.material;
        _materials = _renderer.materials;
 
        if (_autoStart)
        {
            StartGlinting();
        }
    }
 
    /// <summary>
    /// 校验数据,并保证运行时的修改能够得到应用。
    /// 该方法只在编辑器模式中生效!!!
    /// </summary>
    private void OnValidate()
    {
        // 限制亮度范围
        if (minBrightness < 0 || minBrightness > 1)
        {
            minBrightness = 0.0f;
            Debug.LogError("最低亮度超出取值范围[0, 1],已重置为0。");
        }
        if (maxBrightness < 0 || maxBrightness > 1)
        {
            maxBrightness = 1.0f;
            Debug.LogError("最高亮度超出取值范围[0, 1],已重置为1。");
        }
        if (minBrightness >= maxBrightness)
        {
            minBrightness = 0.0f;
            maxBrightness = 1.0f;
            Debug.LogError("最低亮度[MinBrightness]必须低于最高亮度[MaxBrightness],已分别重置为0/1!");
        }
 
        // 限制闪烁频率
        if (rate < 0.2f || rate > 30.0f)
        {
            rate = 1;
            Debug.LogError("闪烁频率超出取值范围[0.2, 30.0],已重置为1.0。");
        }
 
        // 更新亮度差
        _deltaBrightness = maxBrightness - minBrightness;
 
        // 更新颜色
        // 注意不能使用 _v ,否则在运行时修改参数会导致亮度突变
        float tempV = 0;
        Color.RGBToHSV(color, out _h, out _s, out tempV);
    }
 
    /// <summary>
    /// 开始闪烁。
    /// </summary>
    public void StartGlinting()
    {
        isGlinting = true;
        if (_materials != null)
        {
            if (_materials.Length > 0)
            {
                //_material.EnableKeyword(_keyword);
                for (int i = 0; i < _materials.Length; i++)
                {
                    _materials[i].EnableKeyword(_keyword);
                }
 
                if (_glinting != null)
                {
                    StopCoroutine(_glinting);
                }
                _glinting = StartCoroutine(IEGlinting());
            }
        }
    }
 
    /// <summary>
    /// 停止闪烁。
    /// </summary>
    public void StopGlinting()
    {
        isGlinting = false;
        //_material.DisableKeyword(_keyword);
        for (int i = 0; i < _materials.Length; i++)
        {
            _materials[i].DisableKeyword(_keyword);
        }
 
        if (_glinting != null)
        {
            StopCoroutine(_glinting);
        }
    }
 
    /// <summary>
    /// 控制自发光强度。
    /// </summary>
    /// <returns></returns>
    private IEnumerator IEGlinting()
    {
        Color.RGBToHSV(color, out _h, out _s, out _v);
        _v = minBrightness;
        _deltaBrightness = maxBrightness - minBrightness;
 
        bool increase = true;
        while (true)
        {
            if (increase)
            {
                _v += _deltaBrightness * Time.deltaTime * rate;
                increase = _v <= maxBrightness;
            }
            else
            {
                _v -= _deltaBrightness * Time.deltaTime * rate;
                increase = _v <= minBrightness;
            }
            //_material.SetColor(_colorName, Color.HSVToRGB(_h, _s, _v));
 
            for (int i = 0; i < _materials.Length; i++)
            {
                _materials[i].SetColor(_colorName, Color.HSVToRGB(_h, _s, _v));
            }
            //_renderer.UpdateGIMaterials();
            yield return null;
        }
    }
}

 

  • 1
    点赞
  • 33
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
### 回答1: Unity中物体间隔闪烁可能是由于以下几个原因导致的: 1. 光照问题:物体可能处于一个动态光源的影响下,当光源发生变化时,物体的亮度也会发生变化,造成闪烁。解决此问题可以尝试使用静态光源,或者调整光源参数,使光照更加稳定。 2. 材质问题:物体使用的材质可能存在问题,如反射率过高、反射模型设置不当等,导致进入和退出光照区域时产生闪烁现象。解决此问题可以重新调整材质的属性,使其更加适合当前的环境光照。 3. 碰撞体问题:物体存在错位或重叠的碰撞体,导致物体在运动时产生闪烁。解决此问题可以检查物体的碰撞体设置,确保其与其他物体正常交互,并修复碰撞体设置不当的问题。 4. 代码逻辑问题:物体的脚本中可能存在问题,如在更新位置时出现错误的计算或赋值,导致物体闪烁。解决此问题可以检查物体的脚本代码,确保逻辑正确,并修复存在的bug。 以上是一些可能导致Unity中物体间隔闪烁的原因和解决方法,具体还需要根据实际情况进行调试和排查。 ### 回答2: 在Unity中,物体间隔闪烁可能是由于多个原因造成的。其中一种可能是物体的渲染顺序错误导致的。在Unity中,物体的渲染顺序是由它们所处的渲染层级(Render Sorting Layer)和渲染顺序(Order in Layer)决定的。如果两个物体的渲染顺序有误,就可能导致它们交替显示,从而造成间隔闪烁的效果。解决这个问题可以通过在物体的Sprite Renderer组件中调整渲染层级和渲染顺序来改变它们的渲染顺序,从而解决闪烁问题。 另一个可能的原因是光照设置不当导致的。在Unity中,光照的设置会影响物体的表面光照效果,如果光照设置不当,可能会导致物体间隔闪烁。可以尝试调整场景中的光照设置,比如调整灯光的位置、角度和强度,以及调整物体的材质和光照贴图等参数来解决闪烁问题。 此外,物体之间的碰撞和触发也可能导致闪烁。如果物体之间存在碰撞或触发事件,并且这些事件的处理函数中有可能修改了物体的位置或其他属性,可能会导致物体间隔闪烁的效果。解决这个问题可以通过检查碰撞和触发事件的代码,确保其逻辑正确,并避免在处理函数中对物体属性进行不必要的修改。 总结起来,解决Unity中物体间隔闪烁的问题需要分析具体情况,可能的原因包括渲染顺序错误、光照设置不当以及碰撞和触发事件的逻辑错误等。通过调整渲染顺序、光照设置和检查碰撞和触发事件的逻辑,可以解决物体间隔闪烁的问题。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值