unity-lighting-vfx について
Unity 開発者向けに、ライティングとビジュアルエフェクトを解説するリファレンススキルです。照明、グローバルイルミネーション、プローブ、パーティクルに加え、VFX Graph、C# 制御例、注意点を扱います。
主な機能
- 01リアルタイム・ベイク・ミックス照明
- 02グローバルイルミネーションと環境反射
- 03Light Probe と APV
- 04Particle System モジュールのリファレンス
- 05VFX Graph の基礎とパターン
- 06C# によるエフェクト制御例
活用シーン
- 01静的・動的シーンの照明方式を選ぶ
- 02移動オブジェクトの間接照明を設定する
- 03Particle System と VFX Graph を比較する
- 04照明やエフェクトの性能問題を調べる
インストール
コマンドをコピーしてターミナルで実行します。
$
npx skills add https:/ / github.com/ nice-wolf-studio/ unity-claude-skills --skill unity-lighting-vfxインストール後、Claude Code で/unity-lighting-vfxを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
references/lighting-guide.mdparticle-system.mdvfx-graph.md詳細
Unity のライティングとビジュアルエフェクト
ライティングモード
Unity には、照明の計算方法を制御する 3 つのライトモードがあります。
リアルタイムライト
- 実行時に毎フレームライティングを計算します
- 強度、色、位置を動的に変更できます
- Shadow Distance までの距離に影を落とします
- デフォルトでは直接光のみが寄与します(バウンス光はありません)
- 実行時の負荷が高く、特に複雑なシーンやローエンドのハードウェアで顕著です
- 最適な用途:動的なオブジェクト、ちらつきエフェクト、移動する光源
ベイク済みライト
- 計算はUnity Editor 内で行われ、ライティングデータとしてディスクに保存されます
- 実行時には、動的に計算する代わりに事前計算済みデータを読み込みます
- 直接光と間接光の両方をライトマップにベイクします
- 移動するオブジェクト用の情報を Light Probes に保存します
- 実行時にライトのプロパティを変更できず、動的な GameObject を照らしません
- スペキュラーへの寄与はありません
- 最適な用途:静的な背景、複雑な間接光、パフォーマンスが重要なシナリオ
ミックスドライト
- ベイク済みの間接光とリアルタイムの直接光を組み合わせます
- 動作は Lighting ウィンドウの Lighting Mode 設定によって異なります
- リアルタイムの影を落とします(ベイク済みのソフトシャドウではありません)
- 実行時にプロパティを変更できます(リアルタイム部分のみに影響します)
- 完全にベイク済みのライティングより、常に処理負荷が高くなります
- 最適な用途:背景のライティングをベイクしつつ、動的な影を使う場合
重要: ベイク済み/ミックスドのすべてのモードで、Baked Global Illuminationを有効にする必要があります。有効にしない場合、ミックスドライトとベイク済みライトはリアルタイムライトとして動作します。
ライトの種類
ディレクショナルライト
- 無限遠に配置され、一方向に光を放射します
- 光線は平行で、距離に応じた強度の減衰はありません
- 太陽や月をシミュレートします。新しいシーンにはデフォルトで 1 つ含まれます
- プロシージャルスカイシステムと連携し、回転させて時間帯の変化を表現できます
ポイントライト
- 1 点に配置され、全方向に均等に光を放射します
- 強度は逆二乗の法則に従います(距離の二乗に応じて減衰します)
- ランプ、爆発、局所的な照明に使用します
スポットライト
- 1 点に配置され、円錐形に光を放射します
- 円錐角度を調整できます。光は端で減衰します(半影)
- 角度を広げると、より大きなフェード領域ができます
- 懐中電灯、ヘッドライト、サーチライトに使用します
エリアライト
- 長方形または円盤として定義され、表面全体から均一に光を放射します
- 逆二乗の法則に従い、柔らかく控えめな陰影を生み出します
- ベイク専用で、実行時には使用できません
- 街灯、リアルな室内照明に使用します
グローバルイルミネーション
グローバルイルミネーション(GI)は、光が表面間で反射する様子をシミュレートし、リアルな間接光を生成します。
ベイク済み GI
- Progressive Lightmapper(CPU または GPU)を使用して、間接光をライトマップに事前計算します
- 結果はライトマップテクスチャと Light Probes に保存されます
- Lighting ウィンドウの Bake 設定で構成します
- GPU Progressive Lightmapper では、タイルサイズを設定してベイク時間を短縮できます
環境ライティング
Lighting ウィンドウの Environment タブで設定する 3 種類のアンビエント光源:
- Skybox:スカイボックスのマテリアルの色を使い、異なる角度からのアンビエント光を表現します
- Gradient:空、地平線、地面に別々の色を設定し、滑らかにブレンドします
- Color:シーン全体に均一なアンビエント光を設定します
Intensity Multiplier(0~8、デフォルトは 1)でアンビエント光の明るさを制御します。
環境反射
- ソース:スカイボックス、またはカスタムの Cubemap/RenderTexture
- 解像度、圧縮、強度の乗数を設定できます
- Bounces 設定で、オブジェクト間の反射を評価する反復回数を制御します
Light Probes と Adaptive Probe Volumes
Light Probes
- シーン全体の空間でライティング情報を取得します
- 実行時には、最も近いプローブを使って動的な GameObject の間接光を近似します
- 移動するオブジェクトに間接的なバウンス光を与え、LOD システムにも対応します
- Light Probe Groups を使って手動で配置する必要があります
- ベイク済みのライティング情報を保存し、直接光と間接光の両方で機能します
適応型プローブボリューム(APV)
APV は、URP における手動のライトプローブ配置に代わる最新の方法です。
- プローブ配置の自動化 -- ライトプローブグループの手動配置が不要になります
- ピクセル単位のライティング -- オブジェクト単位の手法より優れた品質を実現します
- シーンのベイク -- ベイクセットを使用して複数のシーンをまとめてベイクできます
- ランタイム調整 -- ライティングシナリオとスカイオクルージョンにより動的な変更に対応します
- 大規模ワールドのサポート -- 広大なオープンワールド環境向けにデータをストリーミングします
- データの柔軟性 -- AssetBundles または Addressables から読み込めます
- 可視化ツールを使って、プローブ密度とボリュームサイズを設定できます
リフレクションプローブ
周囲の球状ビューをキューブマップとしてキャプチャし、反射マテリアルに使用します。
種類
| 種類 | 説明 |
|---|---|
| ベイク済み | 静的な GameObject のみをキャプチャします。パフォーマンスを重視する場合に最適です |
| カスタム | カスタムテクスチャを使って動的オブジェクトをキャプチャできます |
| リアルタイム | ゲームプレイ中に更新します。リフレッシュモードを設定できます |
主なプロパティ
- 重要度:複数のプローブが重なる場合の描画優先度
- 強度:シェーダー計算におけるテクスチャの明るさ
- ボックスプロジェクション:室内向けのプロジェクションマッピングを有効にします(URP の設定が必要です)
- ボックスサイズ/オフセット:反射の寄与範囲を定めるワールド空間のバウンディングボックス
- ブレンド距離:遅延プローブのブレンド距離
リアルタイムのオプション
- リフレッシュモード:Awake 時、毎フレーム、またはスクリプト経由
- 時間分割:全フェイスを一度に、個別のフェイス、時間分割なし
パーティクルシステムと VFX Graph の比較
| 機能 | パーティクルシステム | VFX Graph |
|---|---|---|
| シミュレーション | CPU ベース | GPU ベース |
| パーティクル数 | 数千 | 数百万 |
| レンダーパイプライン | すべてのパイプライン | URP/HDRP のみ |
| 制作方法 | インスペクターモジュール | ノードベースのグラフエディター |
| 物理演算 | 組み込みの衝突判定 | カスタム衝突ブロック |
| スクリプト | 完全な C# API | イベントベースの C# API |
| サブエミッター | ネイティブサポート | GPU イベントコンテキスト |
| 最適な用途 | 小規模/中規模のエフェクト、モバイル | 大規模エフェクト、ハイエンド |
選択ガイド:
- モバイル向け、シンプルなエフェクト、CPU 側のスクリプト制御を完全に行う必要がある場合、またはビルトインレンダーパイプラインを対象とする場合は、パーティクルシステムを使用します
- 膨大なパーティクル数、GPU 主導のシミュレーション、複雑なノードベースの制作、または URP/HDRP を使用するハイエンドプラットフォームを対象とする場合は、VFX Graphを使用します
パーティクルシステムのモジュール
| モジュール | 目的 |
|---|---|
| Main | 初期状態:ライフタイム、速度、サイズ、重力、シミュレーション空間 |
| Emission | パーティクルの放出率とタイミング |
| Shape | 放出のためのボリューム/サーフェスと開始時の速度方向 |
| Velocity over Lifetime | パーティクルの経過時間に応じて移動を変更します |
| Noise | 有機的で不規則な動きを生み出す乱流 |
| Limit Velocity over Lifetime | 自然な減速 |
| Force over Lifetime | シミュレートされた物理的な力 |
| Inherit Velocity | サブエミッターパーティクルが親の速度を引き継ぎます |
| Lifetime by Emitter Speed | エミッターの速度に基づいて寿命を調整します |
| Color over Lifetime / by Speed | 経過時間または速度に基づく色の変化 |
| Size over Lifetime / by Speed | 時間または速度に基づく寸法の変化 |
| Rotation over Lifetime / by Speed | 向きの変化 |
| Collision | シーンのジオメトリとのパーティクル衝突 |
| Triggers | パーティクルを衝突トリガーとして指定します |
| Sub Emitters | 他のパーティクルを放出するパーティクル |
| Texture Sheet Animation | テクスチャグリッドのアニメーションフレーム |
| Trails | モーショントレイルの描画 |
| Lights | パーティクルに対するリアルタイムライト |
| External Forces | ウィンドゾーンとフォースフィールド |
| Renderer | 画像/メッシュの変換、シェーディング、オーバードロー |
| Custom Data | カスタムデータをパーティクルに付加します |
VFX Graph の基本
システム
- Spawn System:放出を管理する単一の Spawn Context
- Particle System:Initialize -> Update -> Output の連続処理
- Mesh Output System:単一の Mesh Output Context
コンテキスト
- Spawn:各フレームを実行してスポーン数を計算します。状態:Running、Idle、Waiting。ループ時間、カウント、遅延を設定できます
- Initialize:パーティクルの生成時に実行され、初期状態を設定します。新しくスポーンしたパーティクルに対してブロックを処理します。範囲と容量を設定できます
- Update:生存中のすべてのパーティクルに対して毎フレーム実行されます。位置の積分、回転の積分、経過時間の更新、不要なパーティクルの除去を自動で行います
- Output:パーティクルを描画します(Quad、Mesh など)。出力ポートはありません。描画ブロックをカスタマイズできます
グラフ要素
- ブロック:コンテキスト内に積み重ねられるノードです。それぞれが1つの操作を処理し、上から下へ実行されます
- オペレーター:ブロック/コンテキストのポートに接続する、低レベルのプロパティワークフローノードです
- プロパティ:プロパティワークフローを介して接続できます
- 設定:コンテキストごとに編集できる、接続不可の値です
GPU イベント
GPU がイベントを計算する実験的な機能です(通常のイベントでは CPU が計算します)。ブロックでカスタマイズすることはできません。
よく使うパターン(C#)
ライトの作成と設定
using UnityEngine;
public class LightSetup : MonoBehaviour
{
void Start()
{
GameObject lightObj = new GameObject("Dynamic Light");
Light light = lightObj.AddComponent<Light>();
light.type = LightType.Point;
light.color = Color.yellow;
light.intensity = 2.0f;
light.range = 15f;
light.shadows = LightShadows.Soft;
light.shadowResolution = UnityEngine.Rendering.LightShadowResolution.Medium;
}
}
リアルタイム反射プローブの作成
using UnityEngine;
using UnityEngine.Rendering;
public class ProbeSetup : MonoBehaviour
{
void Start()
{
GameObject probeObj = new GameObject("Realtime Reflection Probe");
ReflectionProbe probe = probeObj.AddComponent<ReflectionProbe>();
probe.size = new Vector3(10, 10, 10);
probe.mode = ReflectionProbeMode.Realtime;
probe.refreshMode = ReflectionProbeRefreshMode.EveryFrame;
probe.resolution = 256;
probe.hdr = true;
}
}
実行時のパーティクルシステム制御
using UnityEngine;
public class ParticleController : MonoBehaviour
{
ParticleSystem ps;
void Start()
{
ps = GetComponent<ParticleSystem>();
// Modify emission rate -- cache module in local variable first
var emission = ps.emission;
emission.rateOverTimeMultiplier = 50f;
// Modify main module
var main = ps.main;
main.startLifetime = 3f;
main.startSpeed = 5f;
main.simulationSpace = ParticleSystemSimulationSpace.World;
}
void OnTriggerEnter(Collider other)
{
// Burst emit particles
ps.Emit(100);
}
void OnDisable()
{
ps.Stop(true, ParticleSystemStopBehavior.StopEmittingAndClear);
}
}
VFX Graph の実行時制御
using UnityEngine;
using UnityEngine.VFX;
public class VFXController : MonoBehaviour
{
VisualEffect vfx;
VFXEventAttribute eventAttr;
void Start()
{
vfx = GetComponent<VisualEffect>();
eventAttr = vfx.CreateVFXEventAttribute();
// Set exposed properties
vfx.SetFloat("SpawnRate", 100f);
vfx.SetVector3("Direction", Vector3.up);
vfx.playRate = 1.5f;
}
void OnTriggerEnter(Collider other)
{
// Send custom event with attributes
eventAttr.SetVector3("position", other.transform.position);
vfx.SendEvent("OnHit", eventAttr);
}
public void StopEffect()
{
vfx.Stop();
}
}
必要に応じた反射プローブの更新
using UnityEngine;
public class ProbeRefresher : MonoBehaviour
{
ReflectionProbe probe;
void Start()
{
probe = GetComponent<ReflectionProbe>();
probe.refreshMode = UnityEngine.Rendering.ReflectionProbeRefreshMode.ViaScripting;
}
public void RefreshReflections()
{
probe.RenderProbe();
}
public bool IsReady()
{
return probe.IsFinishedRendering(probe.RenderProbe());
}
}
避けるべきパターン
ライティングで避けるべきパターン
- リアルタイムライトが多すぎる:リアルタイムライトはそれぞれ、毎フレームの処理負荷を増加させます。静的なライトには、Baked または Mixed を使用してください
- ベイクしたグローバルイルミネーションの有効化を忘れる:これを有効にしないと、Mixed/Baked ライトは警告なく Realtime にフォールバックします
- Importance 値を設定せずに反射プローブを重ねる:ちらつきの原因になります。優先順位を決めるため、必ず Importance を設定してください
- 実行時の動作を期待して Area Light を使用する:Area Light はベイク専用であり、実行時には光を発しません
- Indirect Multiplier を無視する:デフォルトのままでは、反射光が明るすぎたり暗すぎたりすることがあります。ライトごとに調整してください
- Shadow Bias を適切に設定しない:低すぎるとセルフシャドウのアーティファクト(シャドウアクネ)が発生し、高すぎると影がオブジェクトから離れます(ピーターパニング)
- 大きなシーンで Light Probe を手動配置する:自動化されたピクセル単位の品質を得るには、URP では代わりに Adaptive Probe Volumes(APV)を使用してください
パーティクルシステムで避けるべきパターン
- モジュール参照をキャッシュしない:モジュール構造体のプロパティにアクセスするたびに、ネイティブコードへ即座に書き込みが行われます。モジュール変数をキャッシュしてください
- アタッチされたエフェクトに World シミュレーション空間を使用する:パーティクルが移動する親オブジェクトから離れていきます。アタッチされた FX には Local 空間を使用してください
- CPU でパーティクル数を増やしすぎる:Particle System は CPU がボトルネックになります。パーティクルが 10K を超える場合は、VFX Graph を検討してください
- Stop/Clear を忘れる:破棄されずに残ったパーティクルシステムは、見えない状態でも CPU を消費します
VFX Graph で避けるべきパターン
- モバイルのシンプルなエフェクトに VFX Graph を使用する:GPU の処理負荷があり、URP/HDRP が必要となるため、モバイルのシンプルなエフェクトには過剰です
- Initialize で Capacity を設定しない:デフォルトの容量では、GPU メモリを割り当てすぎたり、足りなくなったりすることがあります
- Bounds を無視する:Bounds が正しくないと、エフェクトが表示される範囲内にあってもカリングされます。必ず Initialize コンテキストで Bounds を設定してください
- スロットリングせずに毎フレームイベントを送信する:SendEvent には CPU と GPU の同期コストがかかります。イベントの送信をまとめるか、頻度を抑えてください
主要 API クイックリファレンス
Light (UnityEngine.Light)
| Member | Type | Description |
|---|---|---|
type | プロパティ | LightType(Directional、Point、Spot、Area) |
color | プロパティ | 発光色 |
intensity | プロパティ | 明るさの倍率 |
range | プロパティ | 最大距離(Point/Spot) |
spotAngle / innerSpotAngle | プロパティ | 外側/内側の円錐角 |
shadows | プロパティ | LightShadows(None、Hard、Soft) |
shadowResolution | プロパティ | シャドウマップの品質 |
shadowBias / shadowNormalBias | プロパティ | シャドウのアーティファクトを軽減 |
bounceIntensity | プロパティ | GI のバウンス強度 |
cookie | プロパティ | 投影テクスチャマスク |
cullingMask | プロパティ | レイヤーベースのフィルタリング |
colorTemperature | プロパティ | ケルビン単位の CCT |
lightmapBakeType | プロパティ | ベイク設定 |
bakingOutput | プロパティ | 直近のベイクへの寄与の詳細 |
AddCommandBuffer() | メソッド | 指定したタイミングで GPU コマンドを実行 |
ParticleSystem (UnityEngine.ParticleSystem)
| Member | Type | Description |
|---|---|---|
main / emission / shape | プロパティ | モジュールアクセス用の構造体 |
particleCount | プロパティ | 現在アクティブなパーティクル数 |
isPlaying / isPaused / isStopped | プロパティ | 再生状態 |
Play() / Pause() / Stop() | メソッド | 再生制御 |
Emit(count) | メソッド | パーティクルを即時に生成 |
Simulate(time) | メソッド | シミュレーションを早送り |
GetParticles() / SetParticles() | メソッド | パーティクルデータに直接アクセス |
Clear() | メソッド | すべてのパーティクルを削除 |
TriggerSubEmitter() | メソッド | サブエミッターを有効化 |
VisualEffect (UnityEngine.VFX.VisualEffect)
| Member | Type | Description |
|---|---|---|
visualEffectAsset | プロパティ | エフェクトグラフを割り当て/変更 |
playRate | プロパティ | シミュレーション速度 |
aliveParticleCount | プロパティ | アクティブなパーティクル数 |
Play() / Stop() / Reinit() | メソッド | 再生制御 |
SendEvent(name, attr) | メソッド | グラフイベントをトリガー |
CreateVFXEventAttribute() | メソッド | イベントペイロードを作成 |
SetFloat() / SetVector3() / etc. | メソッド | 公開プロパティを設定 |
GetFloat() / GetVector3() / etc. | メソッド | 公開プロパティを読み取り |
HasFloat() / HasVector3() / etc. | メソッド | プロパティの有無を確認 |
ResetOverride(property) | メソッド | 元の値に戻す |
ReflectionProbe (UnityEngine.ReflectionProbe)
| Member | Type | Description |
|---|---|---|
mode | プロパティ | ベイク済み/カスタム/リアルタイム |
size / center | プロパティ | バウンディングボックスの設定 |
intensity / importance | プロパティ | 明るさと優先度 |
boxProjection | プロパティ | ボックスプロジェクションを有効化 |
refreshMode / timeSlicingMode | プロパティ | リアルタイム更新の設定 |
RenderProbe() | メソッド | キューブマップの更新を強制 |
IsFinishedRendering() | メソッド | 時分割処理の完了を確認 |
BlendCubemap() | メソッド | 2つのキューブマップをブレンド |
関連スキル
unity-graphics-- レンダーパイプライン(URP/HDRP/Built-in)、シェーダー、マテリアル、カメラunity-2d-- 2D ライティング(URP 2D Renderer)、スプライトのレンダリングunity-platforms-- プラットフォーム別のライティング品質設定、モバイル最適化
Additional Resources
コメント
Markdown 対応