mcpField
L
lighting-environment

lighting-environment

github.com/decentralandクリエイティブ・メディア4279 回インストール今日更新
リポジトリ

lighting-environment について

Decentraland SDK7 のシーン開発者向けに、照明と環境の設定を解説するスキルです。動的ライトや空の時刻、自発光素材、描画制限に加え、Creator Hub Smart Items の利用条件も扱います。

主な機能

  1. 01Smart Items による照明追加
  2. 02ポイントライトとスポットライトの設定
  3. 03シャドウとマスクテクスチャの設定
  4. 04空の時刻の制御
  5. 05自発光と周囲の照明の区別

活用シーン

  1. 01シーンにオン・オフ可能な照明を配置
  2. 02描画されないライトのトラブルシューティング
  3. 03昼夜が変化する環境の作成

MCP 対応

Creator Hub MCP が利用できる場合は、ライト用 Smart Items を検索して place_smart_item で配置する手順を示します。利用できない場合は LightSource を手動設定します。

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/decentraland/sdk-skills --skill lighting-environment

インストール後、Claude Code で/lighting-environmentを入力して読み込まれたか確認します。

詳細

Decentraland のライティングと環境

ルール:Creator Hub MCP が利用可能な場合は、ライトに Smart Item を使用してください

ユーザーがライトの追加を求めており、Creator Hub MCP ツール(mcp__creator-hub__*)が利用可能な場合は、LightSource を使用してエンティティを手動で作成する前に、必ず最初に search_catalog を実行してください。Creator Hub カタログには、すぐに使えるライトの Smart Item が含まれています。

  • Spotlight(87c829b3-8e8d-4fcb-9f43-85d3aa9084f6、カテゴリ lights)-- 実際の GLB モデル(assets/asset-packs/spotlight/spotlight.glb)、設定済みの core::LightSource、組み込みの Turn On / Turn Off / Toggle アクション、Creator Hub UI 用の適切な inspector::Config が含まれています。
  • Point Light(カテゴリ lights)-- 同じパターンで、GLB のプレースホルダー、Point タイプに設定済みの core::LightSource、組み込みアクションが含まれています。
  • 装飾用の 「Spotlight」(カテゴリ decorations)もあります。これは LightSource のない、見た目だけの器具モデルです。ユーザーが実際の照明を求めている場合は、必ず lights カテゴリから選んでください。

assetId と position を指定して place_smart_item を使用してください。GLB ファイルのダウンロード、アセットパスの解決、asset-packs::Placeholder、asset-packs::Script、asset-packs::Actions、inspector::Config コンポーネントの設定をすべて処理します。エンティティはアクショントリガーが接続された状態で、すぐにエディターから使用できます。

次の場合に限り、手動で create_entity と set_component を使って core::LightSource を設定する方法に切り替えてください。

  • Creator Hub MCP ツールが利用できない場合(純粋なコードでのワークフロー)。
  • 見た目のモデルがないライト(不可視の光源)が必要な場合。
  • Smart Item では公開されていない標準外のライトパラメーターが必要な場合。

以下に記載する手動での LightSource コンポーネント API は、どちらの方法でも信頼できるリファレンスです。Smart Item でも、同じ基盤となるコンポーネントを使用します。

ルール:3D モデルの照明器具は光を放ちません

GLB モデル内のライトに見える形状(ランプのメッシュ、電球の形状、光るフィラメント)は見た目だけのもので、Decentraland で実際の動的な光を放つことはありません。レンダラーはこれを通常の形状として扱います(発光マテリアルによる光の効果がある場合もありますが、周囲のオブジェクトを照らすことはありません)。照明器具モデルから実際の動的な照明を得るには、同じエンティティ、または光源の位置に配置した子エンティティに LightSource コンポーネントを追加してください。ユーザーが照明器具を内蔵したシーンモデルを使用している場合は、先回りして次のように伝えてください。「モデル内の照明器具は装飾用の形状にすぎません。実際に照らすには LightSource コンポーネントを追加する必要があります。」

ポイントライト

位置を起点に、全方向へ光を放ちます。

import { engine, Transform, LightSource } from '@dcl/sdk/ecs'
import { Vector3, Color3 } from '@dcl/sdk/math'

const light = engine.addEntity()
Transform.create(light, { position: Vector3.create(8, 3, 8) })

LightSource.create(light, {
  type: LightSource.Type.Point({}),
  color: Color3.White(),
  intensity: 16000  // candela
})
色付きポイントライト
LightSource.create(light, {
  type: LightSource.Type.Point({}),
  color: Color3.create(1, 0.5, 0),  // Warm orange
  intensity: 16000,
  range: 15  // Maximum distance in meters
})

デフォルト値(プロトコルの定義):active は true、color は白、intensity は 16000 カンデラ、range は -1(自動)、shadow は false です。color は Color3(RGB、それぞれ 0~1)です。

スポットライト

特定の方向に円錐状の光を照射します。

import { Quaternion } from '@dcl/sdk/math'

const spotlight = engine.addEntity()
Transform.create(spotlight, {
  position: Vector3.create(8, 4, 8),
  rotation: Quaternion.fromEulerDegrees(90, 0, 0)  // Point straight down — +90, not -90 (see below)
})

LightSource.create(spotlight, {
  type: LightSource.Type.Spot({ innerAngle: 25, outerAngle: 45 }),
  color: Color3.White(),
  intensity: 16000
})
  • innerAngle — 最大輝度の円錐角度(度)。デフォルトは 21.8 です。最小値は 0、最大値は 179 です。
  • outerAngle — 外側の減衰角度(度)。デフォルトは 30 です。最大値は 179 です。
  • innerAngle は outerAngle を超えることはできません。超えた場合、エンジンによって同じ値に調整されます。
  • 円錐状の光はエンティティのローカル +Z(前方)に向かって照射されます。Explorer はエンティティのトランスフォームの下に、ローカルポーズを単位行列にした Unity の Light を親として配置します(LightSourceLifecycleSystem.cs、unity-explorer main 2026-10)。X 軸を中心に +90 ピッチすると真下を向き、-90 では空を向きます。@dcl/ecs-math で計算すると(2026-10-22)、Quaternion.fromEulerDegrees(90, 0, 0) は Vector3.Forward() を (0, -1, 0) に回転させ、-90 の場合は (0, 1, 0) に回転させます。SDK ドキュメントのスポットライトの例と、このスキルの以前のバージョンでは「下向き」に -90 と記載されていたため、天井のスポットライトが何も照らしていないように見える場合は、屋根を照らしている可能性があります。ゲーム内ではまだ再確認されていません。Light Limits の下にある確認テストで、円錐の向きを一度確認してください。
  • type は判別共用体です。実行時にスポットライトのパラメーターを読み取ったり変更したりするには、まず型を絞り込みます。 if (comp.type?.$case === 'spot') { comp.type.spot.innerAngle = 30 }

シャドウ

ポイントライトまたはスポットライトでシャドウを有効にします。

LightSource.create(spotlight, {
  type: LightSource.Type.Spot({ innerAngle: 25, outerAngle: 45 }),
  shadow: true,
  intensity: 800
})

注:シャドウがレンダリングされるのはスポットライトのみで、ポイントライトではレンダリングされません。shadow はコンポーネントのトップレベルにあるブール値で、Spot/Point の中にはありません。

シャドウマスクテクスチャ(ゴボ)

ライトを通してパターンを投影します。

const maskedLight = LightSource.getMutable(spotlight)
maskedLight.shadowMaskTexture = Material.Texture.Common({
  src: 'assets/Images/lightmask1.png'
})
  • マスクを再度解除するには、shadowMaskTexture = undefined を設定します。
  • マスクはライトの形状(窓のパターンなど)を投影し、コースティクスやソフトシャドウを表現します。スポットライトで使用します。

ライトの切り替え

// Toggle on/off
const lightData = LightSource.getMutable(light)
lightData.active = !lightData.active

光源の制限

  • シーンでは多数のライトを作成できます(エンジンのテストシーンでは2区画に約9個が配置されます)。実際にいくつ描画するかはレンダラーが決定します。
  • デスクトップの品質プリセットではシーン内のライト数に上限があります。Low = 0(シーン内のライトを完全に無効化)、Medium = 6、High = 10(QualityPresetLow/Medium/High.asset、unity-explorer main 2026-10。設定スライダーでプリセットの上限をさらに下げることもできます)。シーン内のライト数が上限を超えると、プレイヤーに最も近いライトだけが描画されます。
  • 「ライトが表示されない」場合は、まずプレイヤーの現在のプリセットを確認してください。Low では、正しく作成した LightSource も描画されません。強度、範囲、マテリアル、アタッチ位置のオフセットをどれだけ調整しても変わりません。High を求めるのではなく、サポートされる最低設定(Medium)を案内してください。発光する炎が見えても、ろうそくが部屋を照らしている証拠にはなりません。光るメッシュと周囲に当たる光は、別々に確認してください。
  • 影を落とすライトは、同時に最大約3個まで描画されます。
  • レンダラーは品質設定と距離に基づいて、ライトを自動的にカリングします。
  • 強度の単位はカンデラです(1m でのルーメン/m²、つまりルーメン/4π)。デフォルトは 16000 です。
  • range のデフォルト値は -1 で、intensity^0.25(4乗根、メートル単位)として自動計算されます。明示的な range を設定すると上書きできます。これによりライトの影響範囲も制限され、パフォーマンスが向上します。
  • 一度にプレイヤーの近くに多くのライトが集まらないよう、間隔を空けて配置してください(最も近いライトだけが描画されます)。
  • シーン内のライトがまったくなくても、シーンを理解できるようにしてください。 デスクトップの Low とモバイルの Very Low では、シーン内のライトは一切描画されません。また、デスクトップのオーナーによるテスト(2026-10-09)では、同じ部屋でポイントライトは見えた一方、スポットライト2個は暗いままでした(原因は特定されていません)。道筋、インタラクト可能なオブジェクト、「ライトが暖色になる」というストーリー上の場面など、ゲームプレイに不可欠な要素は、発光マテリアル、テクスチャ、スカイボックスで表現できるようにしてください。LightSource はアクセントとして使います。この考え方は「プラットフォームサポート」に記載されたモバイル向けルールにも当てはまります。
  • 何かを調整する前に、1分間の簡易テストを行ってください。 デフォルトの intensity: 16000 で、床から2.5 mの高さにポイントライトを1個置き、同じ高さで真下を向けた(+90)スポットライトを1個置き、比較用に発光する平面も隣に配置します。ポイントライトが見えてスポットライトが暗い場合は、強度ではなく照準またはプリセットに原因があります。どちらも見えない場合は、プリセットが Low です。その後でのみ調整してください。コードに8~60 cd の値を8回試し書きした後(2026-10-08)、この疑問に答えたテストを実施しました。カタログの Point Light / Spotlight スマートアイテムが 16000 から始まるのには理由があります。

SkyboxTime(日夜サイクル)

雰囲気の演出には SkyboxTime を使います。ポイントライトを使った夜のシーンで、印象的な環境を作れます。

scene.json で時刻を固定する

コードを使わずに時刻を固定します。有効な場所は2つあります。

// Genesis City scene — top-level
{ "skyboxConfig": { "fixedTime": 43200 } }

// World — inside worldConfiguration
{ "worldConfiguration": { "name": "my-name.dcl.eth", "skyboxConfig": { "fixedTime": 36000 } } }

時刻の値(午前0時からの秒数。1日は86400秒):0 = 深夜、21600 = 午前6時、43200 = 正午、64800 = 午後6時(日暮れ)、86400 = 1日分。

優先順位(エンジンのテストシーンで確認済み):worldConfiguration.skyboxConfig.fixedTime はトップレベルの skyboxConfig.fixedTime より優先されます。どちらの JSON 値も、実行時には engine.RootEntity 上の SkyboxTime コンポーネントによって上書きされます。

現在のワールド時刻を読み取る
import { getWorldTime } from '~system/Runtime'

executeTask(async () => {
  const time = await getWorldTime({})
  console.log('Seconds since midnight:', time.seconds)
})
時刻を動的に変更する
import { engine, SkyboxTime, TransitionMode } from '@dcl/sdk/ecs'

// Set time of day (must target the root entity)
SkyboxTime.create(engine.RootEntity, { fixedTime: 43200 })  // Noon

// Change with transition direction
SkyboxTime.createOrReplace(engine.RootEntity, {
  fixedTime: 64800,  // Dusk (6 PM)
  transitionMode: TransitionMode.TM_BACKWARD  // TM_FORWARD (0, default) or TM_BACKWARD (1)
})

// Remove the component to hand control back to global/world time
SkyboxTime.deleteFrom(engine.RootEntity)
  • transitionMode(省略可能)は、時刻変更時のアニメーション方向を設定します。デフォルトは TM_FORWARD です。
  • このコンポーネントは engine.RootEntity に配置する必要があります。削除すると、scene.json / ワールドの時刻(またはグローバルの日夜サイクル)に戻ります。
日夜サイクルシステム
let currentTime = 43200
const CYCLE_SPEED = 100  // Time units per second

function dayNightCycle(dt: number) {
  currentTime = (currentTime + CYCLE_SPEED * dt) % 86400
  SkyboxTime.createOrReplace(engine.RootEntity, {
    fixedTime: currentTime
  })
}

engine.addSystem(dayNightCycle)

Realm 情報

プレイヤーが接続している Realm(サーバー)を検出します。

import { getRealm } from '~system/Runtime'

executeTask(async () => {
  const realm = await getRealm({})
  console.log('Realm:', realm.realmInfo?.realmName)
  console.log('Network:', realm.realmInfo?.networkId)
  console.log('Base URL:', realm.realmInfo?.baseUrl)
})

発光マテリアル(グロー効果)

周囲を照らさずに視覚的な光を表現する場合:

import { engine, Material } from '@dcl/sdk/ecs'
import { Color4, Color3 } from '@dcl/sdk/math'

// Self-illuminated material (emissiveColor uses Color3, not Color4)
Material.setPbrMaterial(entity, {
  albedoColor: Color4.create(0, 0, 0, 1),
  emissiveColor: Color3.create(0, 1, 0),  // Green glow
  emissiveIntensity: 2.0
})

注:発光マテリアルは周囲にある他のエンティティを照らしません。マテリアル自体にグロー効果が生じるだけです。

発光マテリアルと LightSource の組み合わせ

見た目に光り、周囲にも光を当てるオブジェクトの場合:

// Visual glow on the mesh
Material.setPbrMaterial(bulb, {
  emissiveColor: Color3.create(1, 0.9, 0.7),
  emissiveIntensity: 1.5
})

// Actual light emission
LightSource.create(bulb, {
  type: LightSource.Type.Point({}),
  color: Color3.create(1, 0.9, 0.7),
  intensity: 200,
  range: 10
})
シャドウの品質

shadow は LightSource コンポーネントのトップレベルに指定する省略可能なブール値です(デフォルトは false)。シャドウの種類を指定する列挙型はありません。品質は距離に基づいて自動的に決まります。Spot({...}) が受け付けるのは innerAngle? と outerAngle? のみです。

import { LightSource } from '@dcl/sdk/ecs'

// Spot light with shadows enabled
LightSource.create(spotEntity, {
  type: LightSource.Type.Spot({ innerAngle: 25, outerAngle: 45 }),
  shadow: true,  // top-level boolean
  intensity: 800
})

制約:

  • シャドウに対応しているのはスポットライトのみです。ポイントライトはシャドウを落としません。
  • 同時にレンダリングできるシャドウ対応ライトは最大 3 個です。シャドウが不要なライトでは shadow を無効にしてください。シャドウ対応のスポットライトは、懐中電灯などのドラマチックな効果に適しています。
  • シャドウの品質とカリングは、プレイヤーからのライトの距離に基づいて自動的に行われます。正確な距離はライトの種類やプレイヤーの品質設定によって異なりますが、一般的な目安は次のとおりです。
プレイヤーからの距離結果
< 10 mソフトシャドウ(高品質)
10–20 mハードシャドウ(低品質)
> 20 mシャドウはレンダリングされません
  • ライト自体は、はるかに遠くまで照射し続けます。無効になるのは、プレイヤーが 160 m(10 区画) を超えて離れた場合のみです。そのため、LightSource は、観客の大半が照明器具から離れた場所にいるライブイベントのステージ照明など、大規模なセットアップに適しています。
  • ライトはプレイヤーがシーンの内側にいる間のみレンダリングされます。外側ではレンダリングされません。

高度なマテリアル効果が必要ですか? 金属度、粗さ、透明度、テクスチャマップ、テクスチャトゥイーン、テクスチャモードについては、advanced-rendering スキルを参照してください。

プラットフォームのサポート

  • デスクトップ(Unity エクスプローラー): フルサポート(ポイントライト、スポットライト、シャドウ)。あるオーナーのテスト(2026-10-09、デフォルトの強度でポイントライト1つとスポットライト2つ)ではポイントライトのみが表示されましたが、再現されておらず、スポットライトが上向きに設定されていた可能性があります(「スポットライト」を参照)。クライアントの不具合と判断する前に、「ライトの制限」の下にある健全性テストを実行してください。
  • モバイル(Godot エクスプローラー): LightSource(シーンの動的ライト)はv1.13.0 以降で利用可能です。プラットフォーム間の対応状況に差はなくなりました。実行時の予算が適用されます。以下を参照してください。
  • Bevy エクスプローラー: フルサポート(ポイントライト、スポットライト、シャドウ)。

2026年10月、ドキュメントのコミット b4d4c88(モバイル対応状況トラッカー)および 8139a7f(モバイルの制限)に照らして確認済みです。

モバイルのライト予算

モバイルでは、作成されたライトに対してシーン全体に適用される上限があります。ライトソースはソフト上限が8個、ハード上限が16個、シャドウ対応ライトはソフト上限が2個、ハード上限が4個です。ソフト上限を超えるとモバイルのパフォーマンスパネルに警告が表示され、ハード上限を超えるとシーンは読み込まれません。

さらに、モバイルの各グラフィックスプロファイルで有効化されるのは、最も近いライトソースのうち予算内のもののみです。Very Low では0個、High では最大8個が有効になります。低いプロファイルではシャドウが完全に無効になる場合もあります。そのため、次の点に注意してください。

  • ライトを20個作成すると、実際に照射するのが最大8個でも、シーン予算をすべて消費します。8個までに抑え、実行時の予算に頼らないでください。
  • ゲームプレイに不可欠な視認性を、特定のライトの点灯に依存させないでください。Very Low では、シーンライトは一切有効になりません。環境光、発光マテリアル、スカイボックスで基本的な視認性を確保し、LightSource はアクセントとして扱ってください。
  • シャドウが有効になる保証はありません。オブジェクトの位置を示す唯一の手がかりとして、シャドウを使用しないでください。

モバイルの制限に関する全表:optimize-scene → モバイルのシーン制限。

注意点

  • range を未設定(-1)にすると、intensity から intensity^0.25 として自動算出されます。intensity が小さいと、range は予想以上に短くなります。減衰を予測可能にするには、range を明示的に設定してください。
  • shadow が影響するのはスポットライトのみです。ポイントライトに設定しても効果はありません。
  • ライトの向きをアニメーションさせるには、ライトのエンティティに Tween/TweenSequence(Rotate モード)を設定します。ビームはエンティティの前方ベクトルに追従します。
  • RootEntity の SkyboxTime は、scene.json の fixedTime を上書きします。deleteFrom を実行すると、その設定に戻ります。
  • ベイク済みのライト用ジオメトリは機能しません。 ランプや電球のメッシュを含む GLB モデルは光を放射しません。実際に照らすには、LightSource コンポーネントを追加してください。上記のルールを参照してください。
  • Smart Item の Placeholder には、テンプレート変数ではなく解決済みのファイルパスが必要です。 asset-packs::Placeholder の src に {assetPath}/spotlight.glb を設定すると、ギズモが表示されない、または壊れた状態になります。place_smart_item はこれを自動的に、たとえば assets/asset-packs/spotlight/spotlight.glb のように解決します。set_component で Placeholder を手動設定する必要がある場合は、実際のディスク上のパスを使用してください。

シーンの例

エンジンチームのテストシーン(実際の API を使用し、エンジンでテスト済み):

コメント