【Unity】ゲームオブジェクトの有効/無効(SetActive)

Unity ゲームオブジェクトの有効/無効(SetActive) C#
Unity ゲームオブジェクトの有効/無効(SetActive)
バージョン
  • Unity 2022.3.45f1

Unityでゲームオブジェクトの有効/無効(アクティブ/非アクティブ)を切り替える方法です。
インスペクターとスクリプトのどちらからも操作できます。

アクティブ切替

Unityエディターでは、インスペクターのチェックでアクティブ/非アクティブの切替ができます。

Inspector

以下のコードでスクリプトからもゲームオブジェクトの状態を制御できます。

//アクティブ
gameObject.SetActive(true);

//非アクティブ
gameObject.SetActive(false);

//現在のアクティブ状態を取得
bool isActive = gameObject.activeSelf;
GameObject-SetActive - Unity スクリプトリファレンス
ゲームオブジェクトをアクティブ/非アクティブにします

親子関係

親オブジェクトが非アクティブになった場合、子オブジェクトは現在の自身のアクティブ状態を保持したまま非アクティブになります。少し分かりにくいですが結論は非アクティブになります。

Cubeを使ってテストしてみます。

Set Active

赤いCubeが親オブジェクト、青いCubeが子オブジェクトです。

空のオブジェクトを作成して次のスクリプトをアタッチします。

using System.Threading.Tasks;
using UnityEngine;

public class ActivationParent : MonoBehaviour
{
    [SerializeField] private GameObject parent;
    [SerializeField] private GameObject child;

    async void Start()
    {
        //アクティブ
        parent.SetActive(true);
        Debug.Log($"親Cube: {parent.activeSelf}");
        Debug.Log($"子Cube: {child.activeSelf}");

        //3秒待機
        await Task.Delay(3000);

        //非アクティブ
        parent.SetActive(false);
        Debug.Log($"親Cube: {parent.activeSelf}");
        Debug.Log($"子Cube: {child.activeSelf}");
    }
}

親オブジェクトが最初はアクティブ、3秒後に非アクティブになります。

アクティブ

Active
gameObject.SetActive(true);

実行開始時点では親オブジェクト、子オブジェクト共にアクティブ状態です。
ヒエラルキー、ゲームビュー、子オブジェクトのインスペクター、コンソールを3秒後にそれぞれ確認します。

非アクティブ

Inactive
gameObject.SetActive(false);

親オブジェクト、子オブジェクト共にビジュアル上は非アクティブになりました。
しかし、子オブジェクトのインスペクターはアクティブ、コンソールログの「gameObject.activeSelf」はtrueとなっています。

非アクティブ時の挙動

先程のスクリプトは削除し、以下のスクリプトを親Cubeにアタッチします。

using UnityEngine;

public class SwitchActivationObject : MonoBehaviour
{
    [SerializeField] public int cntUpCnt = 0;
    [SerializeField] private int onEnableCnt = 0;

    /// <summary>
    /// アクティブ時にコールバック
    /// </summary>
    void OnEnable()
    {
        onEnableCnt++;
        Debug.Log($"OnEnable コール数: {onEnableCnt}");
    }

    void Update()
    {
        Debug.Log($"【Updateメソッド】アクティブ状態: {gameObject.activeSelf}");
    }

    /// <summary>
    /// 外部用コールメソッド
    /// </summary>
    public void CountUp()
    {
        cntUpCnt++;
        Debug.Log($"CountUp コール数: {cntUpCnt}");
    }
}

さらに空のオブジェクトを作成して、以下のスクリプトをアタッチします。

using System.Threading.Tasks;
using UnityEngine;

public class Caller : MonoBehaviour
{
    [SerializeField] private SwitchActivationObject switchAct;
    private GameObject obj;

    async void Start()
    {
        obj = switchAct.gameObject;

        //10回コールしたら終了
        while (switchAct.cntUpCnt < 10)
        {
            await SwitchActive();
        }
    }

    async private Task SwitchActive()
    {
        //1秒待機
        await Task.Delay(1000);

        //アクティブ切替
        obj.SetActive(!obj.activeSelf);

        //外部からのコール
        switchAct.CountUp();
    }
}

1秒ごとにCubeのアクティブ、非アクティブを切り替えます。
さらにCube外のコンポーネントからCube内のコンポーネントにアクセスします。

アクティブ

Active

Updateメソッド、CountUpメソッドが共に実行され正常動作しています。
また、アクティブになった時点でOnEnableメソッドが実行されています。

非アクティブ

Inactive

Updateメソッドは実行されず、CountUpメソッドは実行されました。
各フィールド変数のデータは非アクティブ状態でも更新・保持されています。

まとめ

非アクティブのゲームオブジェクトはUpdateやStart等のライフサイクルメソッドは実行されません。
その他のメソッドやフィールドは非アクティブ時でも有効です。しかし、コール先のメソッド内で別の非アクティブオブジェクトに依存する場合は正常動作しない可能性があります。

タイトルとURLをコピーしました