えんじにあ雑記!

開発していて学んだことをまとめていきます!

MonoBehaviourを継承したクラスのメソッドは今呼ばれているのか、、調査

f:id:flat-M_M:20210417233452p:plain

GameObjectが非アクティブの時、コンポーネントだけが非アクティブの時などの状況でそのメソッドは実行されるのか、、理解が曖昧だったので調査しました。

はじめに

MonoBehaviourを継承したクラスのStartやUpdateなどのメソッド、また独自定義したメソッドなどがGameObjectやComponentのアクティブ/非アクティブなどによって実行されるのかの理解が曖昧だったため調査しました。

検証コード

下記のコードを使って検証しました

using System;
using System.Threading;
using Cysharp.Threading.Tasks;
using UnityEngine;

public class RootComponent : MonoBehaviour
{
    private int _counter;

    private CancellationToken _ct;
    
    private void Awake()
    {
        Log("Awake");
        _ct = this.GetCancellationTokenOnDestroy();
        UniTask.Run(async () =>
        {
            for (var i = 0; i < int.MaxValue; i++)
            {
                _counter++;
                Debug.Log($"Counter incrementation is called");
                await UniTask.Delay(TimeSpan.FromSeconds(0.1f), cancellationToken: _ct);
                _ct.ThrowIfCancellationRequested();
            }
        }, cancellationToken: _ct).Forget(Debug.Log);
    }

    private void OnEnable()
    {
        Log($"OnEnable");
    }

    void Start()
    {
        Log("Start");
    }

    void Update()
    {
        Log("Update");
    }

    private void OnDisable()
    {
        Log($"OnDisable");
    }

    private void OnDestroy()
    {
        Log("OnDestroy");
    }

    public void CalledFromOtherObject()
    {
        Log("CalledFromOtherObject");
    }

    private void Log(string methodName)
    {
        Debug.Log($"{name}.{methodName} is called.");
    }
}

パターン一覧

  1. MonoBehaviourのイベントメソッドでアタッチされているGameObjecetが非アクティブ
  2. MonoBehaviourのイベントメソッドで親のGameObjectが非アクティブ
  3. MonoBehaviourのイベントメソッドでComponentだけが非アクティブ
  4. UniTask.Runで走っている処理でアタッチされているGameObjectが非アクティブ
  5. UniTask.Runで走っている処理でComponentが非アクティブ
  6. 他のスクリプトから呼び出されている独自メソッドでアタッチされているGameObjectが非アクティブ
  7. 他のスクリプトから呼び出されている独自メソッドでComponentが非アクティブ

結果

パターン 結果
1 実行されない
2 実行されない
3 Awakeのみ実行される
4 実行される
5 Awakeで起動していた場合は実行される
6 実行される
7 実行される

備考

Awakeメソッドについて

AwakeはアタッチされているGameObjectが非アクティブの場合には実行されませんが、GameObjectがアクティブでComponentは非アクティブの場合は実行されます。