こんにちわ、Unityエンジニアのオオバです。

MonoBehaviourを継承したクラスには
などのUnityから特定のイベントを受け取れます。

などのメソッド (以降:Unityイベント) です。
これらの関数が実行される条件は
GameObjectまたはコンポーネントがアクティブなとき

※メソッドによって条件は違います

【2021年版】SetActiveとenabledどっちを使うべきかの考察_0

ちなみにアクティブ状態とは👆上のとおり、
チェックが入った状態です。

本記事は
SetActiveとenabledどっちを使うべきかの判断基準
について解説していきます。

GameObjectコンポーネントUnity開発の肝
お互いの特性を理解し、よりよいゲーム設計を目指しましょう。

最後までぜひ読んでみてください。

可能な限りenabledを使い、SetActiveは切り替えない

【2021年版】SetActiveとenabledどっちを使うべきかの考察_1

結論から書くと、やりたいことを実現できるのであれば、
enabledだけで対応すべきです。

というのもSetActiveは負荷が高いから。

基本的にSetActiveは trueのまま
enabledを切り替える という設計が望ましいでしょう。


結論だけ読んでも分かりづらいと思います。
GameObjectとコンポーネントの
特性を把握する必要があります。

ここからはSetActive
enabledの関係について解説していきます。

アクティブ切り替えによる実行メソッドと
その順番の把握が重要です。

※以降はアクティブのことを`ON`
非アクティブを`OFF`というキーワードで解説します。
この記事の内容

その1. GameObject : OFF | コンポーネント : OFF

【2021年版】SetActiveとenabledどっちを使うべきかの考察_2

Unityイベント

その2. GameObject : ON | コンポーネント : OFF

【2021年版】SetActiveとenabledどっちを使うべきかの考察_3

Unityイベント
  1. Awake

その3. GameObject : OFF | コンポーネント : ON

【2021年版】SetActiveとenabledどっちを使うべきかの考察_4

Unityイベント

その4. GameObject : ON | コンポーネント : ON

【2021年版】SetActiveとenabledどっちを使うべきかの考察_5

Unityイベント
  1. Awake
  2. OnEnable
  3. Start
  4. Update(何度も)

ここまでを表にまとめました。

NoGameObjectコンポーネントUnityイベント(数値は順番)
1OFFOFFなし
2ONOFF1.Awake
3OFFONなし
4ONON1.Awake
2.OnEnable
3.Start
4.Update

GameObjectがONにならないと何も動かない
ということが分かります。

その5. その2 → コンポーネント : ON

【2021年版】SetActiveとenabledどっちを使うべきかの考察_6

その2の状態

【2021年版】SetActiveとenabledどっちを使うべきかの考察_7

コンポーネント : ON

Unityイベント
  1. OnEnable
  2. Start
  3. Update

Awakeは呼ばれずに、
OnEnable、Start、Updateと呼ばれます。

その6. その5 → GameObject : OFF → ON

【2021年版】SetActiveとenabledどっちを使うべきかの考察_8

その5の状態

【2021年版】SetActiveとenabledどっちを使うべきかの考察_9

GameObject : OFF

【2021年版】SetActiveとenabledどっちを使うべきかの考察_10

GameObject : ON

Unityイベント
  1. OnEnable
  2. Update

Awake、StartはGameObjectにつき1回だけ呼ばれます。

GameObjectのON / OFFとコルーチンの関係性

【2021年版】SetActiveとenabledどっちを使うべきかの考察_11

コルーチンとGameObjectの関係は切っても切り離せません。
なぜならコルーチンはGameObjectがONのときしか動かないからです。

こちらのコルーチンを実行してみましょう。
2つのログを出力するコードです。

IEnumerator Start()  
{
    Debug.Log("Before Timer");  
    yield return Timer();  
    Debug.Log("After Timer");  
}

IEnumerator Timer()  
{
    yield return new WaitForSeconds(1f);  
    gameObject.SetActive(false);  
}

【2021年版】SetActiveとenabledどっちを使うべきかの考察_12

結果はBefore Timerしか出力されません。

なぜならTimerメソッド内で
GameObjectがOFFになるためです。

GameObjectがOFFになると、
実行中のコルーチン(Startメソッド)は
停止します。

だからDebug.Log("After Timer");は呼ばれないのです。

GmaeObjectとコンポーネントのON / OFFから分かること

【2021年版】SetActiveとenabledどっちを使うべきかの考察_13

ユーザー定義メソッドは常に呼ばれる

ユーザー定義メソッドとは、
以下のようなAwake、Startといった
Unityが予約していないメソッドです。

public void Hoge(){}  

ユーザー定義メソッドは
GameObjectやコンポーネントがOFFだったとしても
外部から呼ぶことができ、処理は走ります。
GameObject、コンポーネントのON / OFF影響をまったく受けません。

【例外】 GameObjectがOFFのときコルーチンは実行できない

【2021年版】SetActiveとenabledどっちを使うべきかの考察_14

コルーチンは例外です。
GameObjectがOFFのコルーチンを実行しようとすると
次のエラーが出力するので注意です。

Coroutine couldn't be started because  
the game object 'GameObject名' is inactive!  

ここまでを表にしてみます。

NoGameObjectコンポーネントUnityイベントコルーチンユーザー関数
1OFFOFFなし不可
2ONOFF1.Awake
3OFFONなし不可
4ONON1.Awake
2.OnEnable
3.Start
4.Update
この結果から分かること

ここからGameObject、コンポーネントの
ON/OFF判断の基準について考察します。

結局SetActiveとenabledどっちを使えばよいのかまとめます。

考察まとめ : SetActiveとenabledどっちを使うべきか

【2021年版】SetActiveとenabledどっちを使うべきかの考察_15

最初の結論でも書きましたが、

SetActiveは負荷が高いため、
やりたいことが実現できるならenabledだけを使うです。

コルーチンを止めたいのであれば、
StopCoroutineを使いましょう。

負荷がかかっても問題ないタイミング、
どうしてもな場合に限ってSetActiveは許容です。

メインはコンポーネントのenabledを切り替える
設計が良い
でしょう。

ただしコンポーネントのON/OFFを
切り替えるのは正直面倒くさいです。

1つのGameObjectにいくつも
複数のコンポーネントがくっついていますからね。

管理的にすごく複雑になり、
SetActiveのON/OFFでシンプルで安全な設計になるのであれば
SetActiveを優先する判断もあり だと思います。

enabled優先論はあくまパフォーマンスにおける理想論です。
その時々で総合的に判断してもらうのが良いかと。


フォローすると UIデザイナー力の上がるTwitter やってます!
今日から使えるテクニックを発信中。
ぜひフォローしてみてください!
👉フォローはこちら!

最後まで読んでいただきありがとうございました!
すばらしいUnityライフをお過ごしください。

期間限定 最大95%オフセール
効率UPメガバンドル開催中!最大95%オフ!!!
期間 : 11月1日午後15時59分まで
オススメ記事
検証環境