在UI背景上实现一个简易的有光影照射的昼夜轮替效果,往往比一个死板的UI背景看起来更加形象生动,比较传统的方式是多图轮流替换的序列帧动画,不过要达到整个UI背景大图的所有地方都产生光影效果,那么务必每张图都是全屏大图,这样的话资源浪费又过于严重了;高端点的话,可以用shader来实现,不过本文会以一种更简单的方式实现这种效果。

主要的思路是为UI背景图片指定一个材质,新建一个默认材质就可以了,让它可以接收光照,然后在指定的位置加入灯光并适当调节,就可以达到很好的光影效果了。

泰课在线
首先在场景中创建一个点光源作为夜晚的月亮,创建一个方向光作为白天的阳光,然后变化这两个灯光的强度以达到昼夜轮替效果,代码如下:

 
//夜晚灯光  
    private Light NightLight;  
    //白天灯光  
    private Light DayLight;  
    //昼夜轮替速度  
    public float _Speed = 0.2f;  
    //一天的时间  
    public int _Time = 3;  
    //昼夜轮替方向  
    private int _Direction = -1;  
    //开启昼夜轮替的时间流逝  
    private bool _IsTimeLapse = false;  
  
    void Start () {  
        NightLight = GlobalManager._Login.FindChild("夜晚灯光").GetComponent<Light>();  
        DayLight = GlobalManager._Login.FindChild("白天灯光").GetComponent<Light>();  
        //初始一天时间结束后昼夜轮替开始  
        StartCoroutine(GlobalManager._Tool.DelayToInvokeDo(delegate() {  
            _IsTimeLapse = true;  
        }, _Time));  
    }  
    void Update () {  
        if (GlobalManager._Login.gameObject.activeSelf)  
        {  
            //开启昼夜轮替  
            if (_IsTimeLapse)  
            {  
                //白天状态  
                if (DayLight.gameObject.activeSelf)  
                {  
                    //通过修改灯光强度以体现时间流逝的效果  
                    DayLight.intensity += Time.deltaTime * _Speed * _Direction;  
                    //白天灯光强度为0,标示着白天结束  
                    if (DayLight.intensity <= 0 && _Direction < 0)  
                    {  
                        //进入夜晚  
                        DayLight.gameObject.SetActive(false);  
                        NightLight.gameObject.SetActive(true);  
                        _Direction *= -1;  
                        return;  
                    }  
                    //白天持续中  
                    if (DayLight.intensity >= 1 && _Direction > 0)  
                    {  
                        _Direction *= -1;  
                        _IsTimeLapse = false;  
                        //一天时间结束后再开启时间流逝  
                        StartCoroutine(GlobalManager._Tool.DelayToInvokeDo(delegate () {  
                            _IsTimeLapse = true;  
                        }, _Time));  
                        return;  
                    }  
                }  
                //夜晚状态  
                if (NightLight.gameObject.activeSelf)  
                {  
                    //通过修改灯光强度以体现时间流逝的效果  
                    NightLight.intensity += Time.deltaTime * _Speed * _Direction;  
                    //夜晚灯光强度为0,标示着夜晚结束  
                    if (NightLight.intensity <= 0 && _Direction < 0)  
                    {  
                        //进入白天  
                        DayLight.gameObject.SetActive(true);  
                        NightLight.gameObject.SetActive(false);  
                        _Direction *= -1;  
                        return;  
                    }  
                    //夜晚持续中  
                    if (NightLight.intensity >= 1 && _Direction > 0)  
                    {  
                        _Direction *= -1;  
                        _IsTimeLapse = false;  
                        //一天时间结束后再开启时间流逝  
                        StartCoroutine(GlobalManager._Tool.DelayToInvokeDo(delegate () {  
                            _IsTimeLapse = true;  
                        }, _Time));  
                        return;  
                    }  
                }  
            }  
        }  
    }  

DelayToInvokeDo是一个延时执行函数,参照我的另一篇博客。
我这里随便找了一张图片,可以看到效果图还是不错的。
白天(阳光最强时):

泰课在线

黄昏(阳光变弱):

泰课在线

夜晚(窗顶上的那个是月亮):