概要
Godot Engineで制作する2Dゲームにおいて、ライティングは単なる装飾以上の役割を果たします。適切に設定された光と影は、シーンに深みと雰囲気を与え、プレイヤーの注意を誘導し、ゲームの世界観を劇的に向上させます。
この記事では、Godotの2Dライティングシステムの核となるPointLight2Dノードと、それを使った 影( シャドウ) の設定方法に焦点を当て、初心者から中級者の方がつまずきやすいポイントを解消しながら、実践的なベストプラクティスを解説します。
この記事を読むことで、あなたは以下のことを習得できます。
- Godot 2Dライティングの基本構造と仕組み
- PointLight2Dノードの基本的な使い方と主要プロパティ
- LightOccluder2Dノードを使った動的な影の生成方法
- ライティング設定で陥りがちな間違いとその解決策
基本概念の解説
Godotの2Dライティングシステムは、主に以下の3つの要素で構成されています。
| 要素 | ノード | 役割 |
|---|---|---|
| 光源 | PointLight2D / DirectionalLight2D | 光を放ち、シーンを照らす。PointLight2Dは点光源、DirectionalLight2Dは太陽光のような平行光源として機能します。 |
| 光を遮るオブジェクト | LightOccluder2D | 光を遮断し、影を生成するための境界を定義します。 |
| 照らされるオブジェクト | CanvasItemを継承するノード (Sprite2D, TileMapなど) | 光源の影響を受け、影を落とす、または影に隠れる対象となります。 |
PointLight2Dの仕組み
PointLight2Dは、特定の点から全方向に光を放射するノードです。その光の形状は、Textureプロパティに設定するテクスチャによって定義されます。一般的に、中央が明るく外側に向かって暗くなるグラデーションテクスチャを使用します。
ヒント: 外部ツールで画像を用意しなくても大丈夫です。
TextureプロパティのプルダウンからNew GradientTexture2Dを選択し、Fillを Radial(放射状) にすることで、きれいな光のグラデーションをエディタ内で作成できます。
主要なプロパティ:
- Texture: 光の形状を定義するテクスチャ。
- Color: 光の色。
- Energy: 光の強度。
- Mode: 光とシーンのブレンド方法(Add, Sub, Mix, Mask)。デフォルトの
Addが最も一般的です。
影の生成: LightOccluder2D
影を生成するためには、光源(PointLight2D)と、光を遮るためのLightOccluder2Dノードが必要です。
- PointLight2D側の設定:
Shadow > Enabledをオンにします。 - LightOccluder2D側の設定: 影を落としたいオブジェクト(壁や障害物など)に
LightOccluder2Dノードを追加し、OccluderプロパティにOccluderPolygon2Dリソースを設定します。このポリゴンが光を遮る境界となります。
よくあるつまずきポイント
初心者が2Dライティングでつまずきやすい、代表的な間違いと誤解を解説します。
影が全く表示されない
PointLight2DのShadow > Enabledをオンにしたのに影が出ない場合、最も多い原因はLightOccluder2Dノードの不足です。
- 間違い:
PointLight2Dを配置し、Shadowを有効にしただけで、影が自動的に生成されると思い込んでいる。 - 真実: Godotの2Dライティングシステムでは、光を遮るための境界を
LightOccluder2Dノードで明示的に定義する必要があります。衝突判定(CollisionShape2D)とは別物です。
シーン全体が真っ暗になってしまう
PointLight2Dを配置した途端、シーン全体が暗くなる、または光が当たっている部分以外が真っ暗になる現象は、CanvasModulateノードやWorldEnvironmentノード の設定が原因であることがあります。
- 解決策:
- CanvasModulate: シーンのルートノードに
CanvasModulateノードがある場合、そのColorが黒(#000000) になっていないか確認してください。これが黒だと、シーン全体が暗くなります。 - LightOccluder2Dの配置ミス: 意図しないオブジェクトに
LightOccluder2Dが設定され、シーン全体を覆うように光を遮断している可能性があります。
- CanvasModulate: シーンのルートノードに
補足:
WorldEnvironmentノードは主に3Dシーン用です。2D/3Dを混在させている場合は環境光の設定が影響す ることもありますが、純粋な2Dゲームであれば、まずはCanvasModulateの色と、各スプライトのModulateプロパティを優先して確認してください。
光源のテクスチャが不自然に見える
デフォルトのPointLight2Dのテクスチャは、光の減衰が急激で不自然に見えることがあります。
- 解決策:
PointLight2DのTextureプロパティに、より滑らかに減衰するカスタムのグラデーションテクスチャを設定します。また、Texture Scaleプロパティを調整して、光の範囲を広げたり狭めたりすることで、自然な見た目に近づけることができます。
影の形がおかしい・逆に出る
LightOccluder2Dを設定したのに影が奇妙な方向に出たり、オブジェクトの内側が影になってしまうことがあります。
- 解決策: OccluderPolygon2Dを描く際の 頂点の順番(時計回り/反時計回り) が影響している可能性があります。インスペクタの
Cull Modeを変更してみるか、ポリゴンの頂点を描く方向を変えてみてください。
ベストプラクティスと実践例
ここでは、よりプロフェッショナルな2Dライティングを実現するための実践的なテクニックを紹介します。
LightOccluder2Dの効率的な設定
タイルマップ(TileMap)を使用している場合、すべてのタイルに個別にLightOccluder2Dを設定するのは非効率的です。
推奨される方法:
- TileSetでOccluderを設定:
TileSetリソース内で、光を遮断したいタイル(壁など)に対してOcclusion Layerを設定します。これにより、TileMapノード全体が単一のLightOccluder2Dとして機能し、パフォーマンスが向上します。 - OccluderPolygon2Dの最適化:
OccluderPolygon2Dを作成する際、頂点(Vertex)の数を必要最小限に抑えます。複雑すぎるポリゴンは描画コストが増加し、パフォーマンスに影響を与えます。
GDScriptによる動的な光源制御
プレイヤーの動きやゲームイベントに応じて光源を動的に制御することで、ゲームプレイに緊張感やリアリティを加えることができます。
例えば、プレイヤーが懐中電灯を持っている場合、その光源をプレイヤーに追従させ、エネルギーが時間とともに減少する処理を実装します。
# Player.gd (PointLight2Dノードを子として持つことを想定)
extends CharacterBody2D
@export var max_light_energy: float = 1.5
@export var energy_drain_rate: float = 0.05 # 1秒あたりの減衰量
@onready var flashlight: PointLight2D = $PointLight2D
func _process(delta: float) -> void:
# プレイヤーの向きに合わせて光源を回転させる(オプション)
# var mouse_pos = get_global_mouse_position()
# flashlight.rotation = (mouse_pos - global_position).angle()
# エネルギーを徐々に減少させる
if flashlight.energy > 0.0:
flashlight.energy -= energy_drain_rate * delta
flashlight.energy = max(0.0, flashlight.energy)
# 懐中電灯のオン/オフ切り替え
if Input.is_action_just_pressed("toggle_light"):
flashlight.enabled = not flashlight.enabled
# エネルギーがゼロになったら自動でオフにする
if flashlight.energy == 0.0:
flashlight.enabled = false
# アイテムなどでエネルギーを回復する関数
func restore_energy(amount: float) -> void:
flashlight.energy += amount
flashlight.energy = min(max_light_energy, flashlight.energy)
if not flashlight.enabled:
flashlight.enabled = true
注意: 上記の例では
toggle_lightという入力アクションを使用しています。「プロジェクト設定」→「入力マップ」からtoggle_lightを追加し、キーボードやゲームパッドのボタンを割り当てておいてください。
Light Occlusionのマスクレイヤー活用
Godot 4では、Light2DノードのItem Cull Maskと、CanvasItemノードのLight Maskプロパティを組み合わせることで、どの光源がどのオブジェクトを照らすかを細かく制御できます。
例えば、「通常光」と「特殊な魔法の光」を分けたい場合、以下のように設定します。
- 通常光 (
PointLight2D):Range > Item Cull Maskをレイヤー1に設定。 - 魔法の光 (
PointLight2D):Range > Item Cull Maskをレイヤー2に設定。 - 通常のオブジェクト (
Sprite2Dなど):Visibility > Light Maskのレイヤー1をオンにする。 - 魔法の光にのみ反応するオブジェクト:
Visibility > Light Maskのレイヤー2をオンにする。
これにより、複雑なシーンでもライティングの適用範囲を論理的に分離し、パフォーマンスの最適化にも繋がります。
注意: Godot 4ではプロパティ名が変更されています。光源側は
Range > Item Cull Mask、照らされる側はVisibility > Light Maskとなっています。
まとめ
Godotの2Dライティングは、PointLight2DとLightOccluder2Dの組み合わせを理解することが成功の鍵です。
- PointLight2D: 光源そのもの。テクスチャとエネルギーで光の見た目を調整します。
- LightOccluder2D: 影を落とすための境界。影を生成するには必須のノードです。
これらの基本をマスターすれば、あなたの2Dゲームは、単調な平面表現から、光と影が織りなす深みのある世界へと進化するでしょう。次に学ぶべきステップとしては、**法線マップ(Normal Map)**を使ったよりリアルなライティング表現や、カスタムシェーダーによる光の表現の拡張に挑戦することをお勧めします。