今日速览
- Godot 2D 场景默认是「无光照」(unshaded)——快,但看着发平。想要光影深度,得手动搭一套 2D 光照节点,它不会自己出现。
- 一套完整光照 = CanvasModulate(环境底色)+ PointLight2D / DirectionalLight2D(光源)+ LightOccluder2D(挡光、投阴影)+ 会受光的 Sprite2D / TileMapLayer。
- 一个 canvas 只能有一个 CanvasModulate;UI(HUD、菜单)要放进独立的 CanvasLayer,否则会跟着变暗、甚至被照亮。
- 引擎的背景色不吃光照:要背景也受光,就得铺一层 Sprite2D 背景,并开启属性的 Texture > Repeat。
- 光照是逐像素开销,灯越大越贵;用
range_layer_min/max与light_mask把光源限制在「该被照亮的东西」上,是效果与性能的双保险。
核心学习内容
1. 先理解「为什么默认没光」
Godot 的 2D 渲染默认不做光照计算:每个 Sprite 直接把贴图颜色画出来,所以画面永远是「全亮」的。2D 光照的思路不是「把变暗的地方照亮」,而是反过来——用 CanvasModulate 把整个画面压成环境暗色,再用 Light2D 把光「加」回来。这就是为什么少了 CanvasModulate,光只会越加越亮、越加越白。
2. 五个节点,各司其职
| 节点 | 作用 | 关键点 |
|---|---|---|
CanvasModulate | 定义「照不到光的地方」是什么颜色(环境底色) | 每个 canvas 仅一个;颜色即环境色 |
PointLight2D | 火把、灯光、子弹、爆炸等位置光 | texture 决定形状与大小,energy 决定强度 |
DirectionalLight2D | 太阳 / 月光,全局平行光 | 靠旋转控制方向,适合昼夜 |
LightOccluder2D | 定义挡光/投阴影的轮廓 | 可独立放置,也可内嵌在 TileMapLayer 的瓦片上 |
Sprite2D / TileMapLayer | 接受光照的表面 | 背景要受光必须用 Sprite2D 并开 Repeat |
要点:阴影只出现在 PointLight2D 覆盖的范围内,方向由光源中心决定;PointLight2D 的 texture_scale 放大光圈很方便,但光圈越大覆盖像素越多、越费性能,别一把梭开满屏。
3. 昼夜循环怎么搭
昼夜循环的本质是用一个 0→1 的时间变量去驱动几个颜色/角度参数:
- 环境色:用一个
Gradient存「午夜—清晨—正午—黄昏—午夜」几段色标,gradient.sample(time_of_day)直接取当前环境色,赋给CanvasModulate.color。手调十几个 if 的时代过去了。 - 太阳:
DirectionalLight2D.rotation_degrees随时间转一圈,energy正午 1.0、夜里压到接近 0,颜色从暖白平滑过渡到冷蓝。 - 时间本身:
time_of_day += delta / day_length_seconds,取小数部分即可无缝循环。
# 每帧推进,昼夜无缝循环
time_of_day = fmod(time_of_day + delta / day_length_seconds, 1.0)
canvas_modulate.color = ambient_gradient.sample(time_of_day)
sun.rotation_degrees = time_of_day * 360.0
4. 三个最容易踩的坑
- UI 被照亮或变暗 → HUD/菜单挂在
CanvasLayer下,与游戏世界分开渲染。 - 背景一片死黑不受光 → 背景改成 Sprite2D +
Texture > Repeat = Enabled。 - 灯光误伤 HUD / 远景 → 用
range_layer_min/max限制光源影响的层,或用light_mask指定哪些对象吃这盏灯。
🎯 DeepSeek 提示词
提示词 1:生成 Godot 4「昼夜循环」脚本(适用:需要时间系统的 2D 游戏)
角色:你是一位 Godot 4(GDScript)游戏开发工程师。
任务:写一个可复用的「昼夜循环」脚本 DayNightCycle.gd,挂在场景中一个 Node2D 上。
需求:
1) 用可导出的 float time_of_day(0.0=午夜,0.5=正午,1.0=回到午夜)驱动;
2) 可导出 day_length_seconds(一天对应现实秒数,默认 120),在 _process 里按 delta 推进并循环;
3) 用可导出的 Gradient 控制环境色,取 gradient.sample(time_of_day) 赋给场景唯一的 CanvasModulate.color;
4) 同时驱动一个 DirectionalLight2D:rotation_degrees 随 time_of_day 转一圈,energy 在正午 1.0、夜晚 0.05 之间平滑过渡,颜色由暖白渐变到冷蓝;
5) 暴露 signal hour_changed(t),供音乐、怪物刷新等系统订阅。
约束:
- 必须用 Godot 4.x 语法(@export、@onready),不要 Godot 3 写法;
- 找不到 CanvasModulate 或 DirectionalLight2D 时用 push_warning 提示,不要直接崩溃;
- 关键行加中文注释。
输出:先给完整 GDScript 代码块,再附 3 行使用说明。
提示词 2:做「跟随玩家的光源 / 手电筒」(适用:俯视 / 恐怖 / 探索类 2D)
角色:你是一位 Godot 4 专家。
任务:给俯视角 2D 游戏做一个跟随玩家的光源(火把或手电筒),用 PointLight2D 实现。
需求:
1) 新建 PlayerLight.tscn,PointLight2D 作为 Player 的子节点,脚本中用 lerp 平滑跟随目标位置,避免抖动;
2) 火光「呼吸」:energy 在 0.85~1.0 之间小幅波动,用 FastNoiseLite 或 sin 噪声模拟火焰;
3) 用 texture_scale 控制光圈大小,并暴露 set_radius(px) 方法;
4) 说明如何确保这盏灯不影响 UI:给出 range_item_cull_mask 与 range_layer_min/max 的正确配法。
约束:Godot 4.x GDScript;每行关键代码加中文注释。
输出:GDScript 代码 + 场景节点结构树 + 3 条参数调优建议。
提示词 3:光照出问题时的 Debug 提示词(适用:排查渲染类 bug)
角色:你是一位 Godot 4 图形/渲染排查专家。
背景:我在 Godot 4 的 2D 场景里加了 CanvasModulate + PointLight2D,但现在【光照完全不生效 / 整个画面发黑 / 我的 UI 也被照亮了】(替换成你的真实现象)。
请按以下格式回答:
1) 最可能的 3 个原因,按概率从高到低排序,每条解释「为什么会导致这个现象」;
2) 每个原因给出一步到位的修复操作(写清在哪个节点的哪个属性、改成什么值);
3) 给一份最小可复现自检清单,从 Project Settings 到节点属性逐项勾选。
约束:只针对 Godot 4.x;不确定的地方明确标注「需确认」,不要编造 API。
输出:Markdown 表格。
学习心得
到这一步,「用 DeepSeek 做一款 Steam 游戏」的画面质感拼图基本齐了:素材(AI 出图)、渲染(像素完美)、动效(Juice)、现在再加上光照与时间。许多独立游戏能靠「氛围」在 Steam 商店页的第一张截图里胜出,而 2D 光照正是氛围性价比最高的一环——一个 CanvasModulate 加几盏 PointLight2D,就能让同一张地图从「还行」变成「有故事」。对 AI 协作来说,这类系统特别适合交给 DeepSeek:需求边界清晰(时间变量 → 颜色/角度)、API 固定、又好验证,是「让 AI 写、你来调」的最佳练兵场。
明日关注
- 把昼夜循环接到游戏里:让夜晚刷更强的敌人、BGM 随昼夜切换(呼应音频总线那几篇)。
- 试一次 AI 生成「光照贴图(light blob)」:让 DeepSeek 出绘图提示词,做一张柔和火把光圈,风格与现有像素素材统一。
- 给主光源加
shadow_filter与 LightOccluder,观察阴影质量与帧率的权衡,记下适合自己项目的参数。
本文由自动化学习流水线每日生成,坚持即学即记。
评论