美文网首页unity
[Unity 3d] 实现黑夜/白天一键切换全攻略

[Unity 3d] 实现黑夜/白天一键切换全攻略

作者: 雨落随风 | 来源:发表于2019-09-15 23:55 被阅读0次

    在本文,笔者讲简单的讲一讲怎么在 Unity 中实现黑夜白天的一键切换。

    演示:

    场景中的灯效,除了直射光其他均是烘焙出来的。


    色彩太丰富,实在不敢录太长时间

    原理:

    如果想要实现上面的这个黑夜白天切换效果,控制好以下几点就行了:

    1. 保证烘焙黑夜和白天光照贴图使用的是同一个场景(Ctrl+D挺好用)。
    2. 动态切换 黑夜和白天的 光照贴图设置(LightmapSettings)。
    3. 动态修改天空盒白天和黑夜对应的天空盒,或者像上面演示的那样:仅仅修改天空盒曝光值。
    4. 修改直射光的强度(如果有必要,可以修改直射光的角度)。
    5. 如果像演示中的镜面建筑,加了光照探针(ReflectionProbe)的需要指定对应的烘焙OK的贴图。
    6. 关于黑夜白天差异性的游戏对象:
      • 不参与烘焙的,比如上面的效果晚上多加的 Lens 辉光,直接白天显示隐藏晚上显示即可。
      • 参与烘焙的,可以直接使用显示 / 隐藏操作。
      • 参与烘焙的,也可以存为预制体动态加载,但该方案要写点代码保证游戏对象上烘焙的光照信息能被加载出来。

    示例:

    using System.Linq;
    using UnityEngine;
    using DG.Tweening;
    
    public class TestSwitchBakedLightMap : MonoBehaviour
    {
        [Header("Common Configuration and Component ")]
        public ReflectionProbe reflectionProbe;
        public Light directLight;
        public GameObject effectLights; //晚上要打灯,白天不打灯
    
        [Header("Configuration and Component For Day"), Space(10)]
        public LightDataConfiguration dayConfig;
        public Cubemap dayReflect;
        public float daySkyboxExposure = 1f;
        public float directLightDayIntensity = 1;
        public float dayLightIntensityMultiplier = 1;
    
        [Header("Configuration and Component For Night"), Space(10)]
        public LightDataConfiguration nightConfig;
        public Cubemap nightReflect;
        public float nightSkyboxExposure = 0.2f;
        public float directLightNightIntensity = 0.2f;
        public float nightLightIntensityMultiplier = 0.3f;
    
        // private fields
        LightmapData[] day;
        LightmapData[] night;
        bool isDay = true;
    
        private void Start()
        {
            night = nightConfig.Lightmaps
                .Select(x => new LightmapData() { lightmapColor = x.lightmapColor, shadowMask = x.shadowMask })
                .ToArray();
            day = dayConfig.Lightmaps
                .Select(x => new LightmapData() { lightmapColor = x.lightmapColor, shadowMask = x.shadowMask })
                .ToArray();
            RenderSettings.skybox.SetFloat("_Exposure", daySkyboxExposure);
            reflectionProbe.customBakedTexture = dayReflect;
        }
    
        void OnGUI()
        { 
            if (GUILayout.Button(isDay ? "To Night" : "To Day"))
            {
                SwithDayAndNight();
            }
        }
    
        public void SwithDayAndNight()
        {
            if (!isDay)
            {
                // 切换为白天的配置
                LightmapSettings.lightmaps = day;
                directLight.DOIntensity(directLightDayIntensity, 0.5f);
                DOTween.To(()=> RenderSettings.ambientIntensity, y=> { RenderSettings.ambientIntensity = y; },dayLightIntensityMultiplier,0.5f);
                RenderSettings.skybox.DOFloat(daySkyboxExposure, "_Exposure", 0.5f);
                effectLights.SetActive(false);
                reflectionProbe.mode = UnityEngine.Rendering.ReflectionProbeMode.Custom;
                reflectionProbe.customBakedTexture = dayReflect;
            }
            else
            {
                // 切换为晚上的配置
                LightmapSettings.lightmaps = night;
                directLight.DOIntensity(directLightNightIntensity, 0.5f);
                DOTween.To(()=> RenderSettings.ambientIntensity, y=> { RenderSettings.ambientIntensity = y; },nightLightIntensityMultiplier,0.5f);
                RenderSettings.skybox.DOFloat(nightSkyboxExposure, "_Exposure", 0.5f);
                effectLights.SetActive(true);
                reflectionProbe.customBakedTexture = nightReflect;
            }
            isDay = !isDay;
        }
    }
    

    Tips:

    • 仅仅是将原理中提到的几点找到对应的 API 通过代码动态修改罢了,仅供熟悉API.
    • 使用了 DoTween 的非扩展方法形式的缓动,可以熟悉下。
    • 使用了 DoTween 的扩展方法形式对天空盒(材质球)的曝光值进行了缓动。
    • 使用了 ScriptableObject 分别保存的黑夜/白天的光照贴图设置信息,只需要 lightmapColor 和 shadowMask 两组信息,使用 ScriptableObject 在本示例中的好处可要好好体会体会哈~
    • 演示中没有出现原理中第六条第三点提到的问题,所以示例代码没做演示。

    扩展阅读:

    1. Unity5.x场景优化之动态设置光照贴图lightmap - yuyingwin的专栏 - CSDN博客
      ↑怎么让动态加载的游戏对象实例化后自动加载光照贴图效果:↑

    2. [Unity3D]Lightmapping使用及动态加载lightmap方案 - bread's code - CSDN博客
      ↑更多关于光照贴图+光照探针的参考资料↑

    转载请注明出处,谢谢!

    相关文章

      网友评论

        本文标题:[Unity 3d] 实现黑夜/白天一键切换全攻略

        本文链接:https://www.haomeiwen.com/subject/wcimyctx.html