U
章 04世界与游戏循环7 课 — 点击打开
02 / 07 · 10 分钟
世界与游戏循环

光照与天空盒

到目前为止的项目

Assets/

Scenes/

Arena.unity

TerrainMixed Directional Light

Scripts/

DayNight.cs

项目设置

baked lightmapsskybox + fog

你已经有的这一课新增

照亮你地形的,正是 tab 01 里你旋转过的那个 Directional Light。站在上面的 Knight 连一个像样的影子都没有。这两样在这节课里一起解决。

光照比任何模型都更能决定游戏的观感,而其中大部分工作是一个 Directional Light 完成的。

动态图解

转动太阳,整个氛围、影子方向和天空颜色都会跟着变。

你会用到的三种灯光

  • Directional —— 太阳。位置无关紧要,只有旋转有意义。每个场景一个。

  • Point —— 灯泡,向四面八方辐射。火把、台灯、魔法球。

  • Spot —— 锥形。手电筒、路灯、舞台灯。

合理的太阳默认设置

  1. 1

    Rotation 50, -30, 0 —— 高度足够照亮脸,倾斜足够让影子看得清。

  2. 2

    Intensity 大约 1.0–1.3,颜色是稍微偏暖的白(#FFF4E0)。

  3. 3

    Shadow Type = Soft Shadows,Strength 大约 0.8。纯黑的影子看起来像 bug。

实时还是烘焙

✖ Realtime

会动的东西用它才对,不动的东西用它就是浪费。

✓ Baked lightmaps

在编辑器里算一次,运行时零开销。手游看起来好看就是靠这个。
  1. 1

    把所有从来不动的物体都选中,在 Inspector 右上角勾上 Static。Knight 不是静态物体 —— 别动它。

  2. 2

    把 Directional Light 的 Mode 设为 Mixed:它既烘焙到静态物体上,也继续照亮移动的玩家。

  3. 3

    打开 Window▸Rendering▸Lighting,然后按 Generate Lighting。

  4. 4

    调试时 Lightmap Resolution 先用 10,只在最后一次烘焙才提到 30–40。

天空盒、环境光与雾

  • 天空盒不只是背景板 —— 它是照在每一个表面上的环境光主要来源。

  • 在 Lighting > Environment 里把 Ambient Source 设为 Skybox,Intensity 0.8–1.0,暗部就有自然的补光。

  • 雾能藏起远裁剪面,还能让你把摄像机的 Far distance 调小 —— 这是白捡的性能。

  • 雾的颜色要和天空盒地平线的颜色一致,否则接缝一眼就看出来。

12 行代码做出昼夜循环

DayNight.cs — attach to the Directional Light
using UnityEngine;

public class DayNight : MonoBehaviour
{
    [SerializeField] private float dayLengthMinutes = 4f;
    [SerializeField] private Gradient sunColor;          // paint dawn → noon → dusk
    [SerializeField] private AnimationCurve intensity;

    private Light sun;
    private float t;                                     // 0 .. 1 across a full day

    void Awake() => sun = GetComponent<Light>();

    void Update()
    {
        t += Time.deltaTime / (dayLengthMinutes * 60f);
        t %= 1f;

        transform.rotation = Quaternion.Euler((t * 360f) - 90f, 30f, 0f);
        sun.color = sunColor.Evaluate(t);
        sun.intensity = intensity.Evaluate(t);

        RenderSettings.ambientIntensity = Mathf.Lerp(0.2f, 1f, sun.intensity);
    }
}