CanvasGroupとは?
UIを作っていると、パネルやダイアログの表示・非表示を切り替えたり、フェードさせたい場面がよくあります。
そのとき、パネル内のButtonやImageを一つずつ操作するのは手間がかかりますし、管理も複雑になりがちです。
CanvasGroupは、こうした課題を解決するためのコンポーネントです。
GameObjectにアタッチするだけで、そのオブジェクトと子オブジェクトすべてのUI要素に対して、透明度・操作可否・レイキャストのブロックをまとめて制御できます。
たとえばalphaを0にするだけでパネル全体を透明にしたり、interactableをfalseにするだけで全ボタンを一括で無効化したりできます。
個別に制御するコードを書く必要がなくなるので、UIまわりの実装がシンプルになります。
プロパティの解説
CanvasGroupには4つのプロパティがあります。

alpha
グループ全体の透明度を0〜1の範囲で設定します。
0で完全に透明、1で完全に不透明です。
この値は子要素のアルファ値と乗算で合成されます。
たとえばCanvasGroupのalphaが0.5で、子のImageのアルファも0.5の場合、実際の表示は0.25になります。
interactable
trueの場合、グループ内のUI要素は通常どおり操作できます。
falseにすると、グループ内のすべてのSelectableコンポーネント(Button、Slider、Toggleなど)が操作不能になります。
ナビゲーションも無効化されるため、キーボードやゲームパッドでの操作もできなくなります。
blocksRaycasts
trueの場合、Graphic Raycasterのレイキャストをブロックします。
falseにすると、グループ内のUI要素をクリックやタッチがすり抜けるようになります。
パネルを非表示にする際はalphaを0にするだけでなく、blocksRaycastsもfalseにしておかないと、見えないUIが背後のタッチを奪ってしまいます。これは意外とハマりやすいポイントです。
ignoreParentGroups
通常、子のCanvasGroupは親のCanvasGroupの影響を受けます。
ignoreParentGroupsをtrueにすると、親のCanvasGroupのalphaやinteractableなどの設定を無視できます。
たとえば、パネル全体をフェードアウトさせたいけれど、特定の子要素だけは常に表示しておきたい場合などに使えます。
基本的な使い方
パネルの表示・非表示をCanvasGroupで切り替える例です。
alpha、interactable、blocksRaycastsをまとめて操作することで、表示状態を制御します。
using UnityEngine;
public class PanelController : MonoBehaviour
{
[SerializeField] private CanvasGroup _canvasGroup;
// パネルを表示する
public void ShowPanel()
{
_canvasGroup.alpha = 1f;
_canvasGroup.interactable = true;
_canvasGroup.blocksRaycasts = true;
}
// パネルを非表示にする
public void HidePanel()
{
_canvasGroup.alpha = 0f;
_canvasGroup.interactable = false;
_canvasGroup.blocksRaycasts = false;
}
}

ShowPanelで3つのプロパティをすべて有効にし、HidePanelですべて無効にしています。
HidePanelのときblocksRaycastsもfalseにしているのがポイントです。
これを忘れると、透明なパネルが背後のUIへのタッチをブロックしてしまいます。
実践的な使い方
コルーチンによるフェードイン・フェードアウト
alphaを徐々に変化させれば、パネルのフェードイン・フェードアウトも実現できます。
using System.Collections;
using UnityEngine;
public class PanelFader : MonoBehaviour
{
[SerializeField] private CanvasGroup _canvasGroup;
[SerializeField] private float _fadeDuration = 0.3f;
public void FadeIn()
{
StartCoroutine(Fade(0f, 1f));
}
public void FadeOut()
{
StartCoroutine(Fade(1f, 0f));
}
private IEnumerator Fade(float from, float to)
{
var elapsed = 0f;
// フェード開始時に操作を設定する
_canvasGroup.interactable = false;
_canvasGroup.blocksRaycasts = true;
while (elapsed < _fadeDuration)
{
elapsed += Time.deltaTime;
_canvasGroup.alpha = Mathf.Lerp(from, to, elapsed / _fadeDuration);
yield return null;
}
_canvasGroup.alpha = to;
// フェード完了後に操作状態を反映する
var isVisible = to > 0f;
_canvasGroup.interactable = isVisible;
_canvasGroup.blocksRaycasts = isVisible;
}
}

FadeメソッドでMathf.Lerpを使い、alphaを徐々に変化させています。
フェード中はinteractableをfalseにして誤操作を防ぎ、完了後に表示状態に応じて操作可否を切り替えています。
ダイアログ表示中に背後のUIを無効化する
ダイアログを表示しているとき、背後のUIをタッチできないようにしたい場面は多いです。
背後のパネルにもCanvasGroupを付けておけば、簡単に実現できます。
using UnityEngine;
public class DialogManager : MonoBehaviour
{
[SerializeField] private CanvasGroup _mainUICanvasGroup;
[SerializeField] private CanvasGroup _dialogCanvasGroup;
// ダイアログを表示し、背後のUIを無効化する
public void OpenDialog()
{
// 背後のUIを操作不能にする
_mainUICanvasGroup.interactable = false;
_mainUICanvasGroup.blocksRaycasts = false;
// ダイアログを表示する
_dialogCanvasGroup.alpha = 1f;
_dialogCanvasGroup.interactable = true;
_dialogCanvasGroup.blocksRaycasts = true;
}
// ダイアログを閉じて、背後のUIを復帰させる
public void CloseDialog()
{
// ダイアログを非表示にする
_dialogCanvasGroup.alpha = 0f;
_dialogCanvasGroup.interactable = false;
_dialogCanvasGroup.blocksRaycasts = false;
// 背後のUIを復帰させる
_mainUICanvasGroup.interactable = true;
_mainUICanvasGroup.blocksRaycasts = true;
}
}
背後のUIはinteractableとblocksRaycastsをfalseにして操作を無効化しています。
alphaは変えていないので、背後のUIは見えたまま操作だけができなくなります。
SetActive(false) との使い分け
UIを非表示にする方法として、GameObject.SetActive(false)を使う方法もあります。
それぞれの違いを把握しておくと、場面に応じた判断がしやすくなります。
SetActive(false) の特徴
GameObjectが非アクティブになるため、描画もコンポーネントの処理も完全に停止する- 実行中のコルーチンが中断され、再アクティブ化しても再開されない
OnEnable、OnDisableが呼ばれるため、副作用が発生する場合がある- 非アクティブな
GameObjectはFind系メソッドで検索できなくなる
CanvasGroup の特徴
GameObjectはアクティブのままなので、コルーチンやUpdateは動き続けるalphaを0にしても描画コストは発生する(後述の注意点を参照)- 表示・非表示の切り替えが滑らかにできる(フェード処理など)
interactableやblocksRaycastsで操作だけを無効化できる
使い分けの指針
フェードなどの演出を伴う場合や、非表示中もコルーチンを動かしたい場合はCanvasGroupが向いています。
一方、完全に不要なUIを非表示にして描画コストを削減したい場合はSetActive(false)が適切です。
両者を組み合わせることも有効です。フェード完了後にSetActive(false)で非アクティブにすれば、演出と描画コスト削減の両立ができます。
注意点
alpha=0でもレイキャストをブロックする
alphaを0にしてもUIが透明になるだけで、blocksRaycastsがtrueのままだとレイキャストはブロックされ続けます。
非表示にしたいならblocksRaycastsもfalseにすること。ここを忘れると、「なぜかボタンが押せない」という原因不明のバグに繋がります。
alpha=0でも描画コストが発生する
alphaを0にしてもGameObjectはアクティブなままなので、描画パスの処理は行われます。
長時間非表示にするUIの場合はSetActive(false)を併用して、描画コストを抑えることを検討してください。
パフォーマンスへの配慮
CanvasGroupのプロパティを変更すると、所属するCanvasのリビルドが発生する場合があります。
フェード処理など毎フレームalphaを更新するケースでは、対象のUIを別のCanvas(Sub Canvas)に分離しておくと、リビルドの影響範囲を限定できます。
まとめ
CanvasGroupは、透明度・操作可否・レイキャストをグループ単位で一括制御できるコンポーネントです。
フェードやダイアログの背後の無効化など、UIでよくある実装パターンとも相性が良く、SetActive(false)とは違った使い道があります。
ただしalphaを0にしてもblocksRaycastsや描画コストは残ります。
この挙動を知らないと原因のわかりにくいバグに繋がるので、頭の片隅に入れておいてください。