【Unity】独自クラスの継承の場合のStart()メソッドの振る舞い

2024年9月8日

Unityには、Start()メソッドやUpdate()メソッドなど、イベント関数が用意されています
Start()メソッドはゲーム開始時でゲームオブジェクトが有効になった時に1回だけ実行されます

サンプルでは、2つのゲームオブジェクトを作成して、それぞれ同じスクリプトをアタッチします
ただし、スクリプトは基底クラスから継承された派生クラスになります

サンプルの概要

2つのゲームオブジェクトを作成しておきます
2つとも同じEnemyStatusスクリプトをアタッチしています
ただし、このEnemyStatusは、MobStatusを継承しています

EnemyStatusをゲームオブジェクトにアタッチするためMobStatusはMonoBehaviourを継承します

コード

2つのゲームオブジェクトにEnemyStatusスクリプトだけアタッチします
MobStatusスクリプトのアタッチは不要です

gameObject.nameは、スクリプトがアタッチされているゲームオブジェクト名を取得します

MobStatus.cs

using UnityEngine;

public class MobStatus : MonoBehaviour
{
    protected virtual void Start()
    {
        Debug.Log($"{gameObject.name}のMobStatus Start");
    }
}

EnemyStatus.cs

base.Start();のbaseとは、基本という英単語で、基底クラスを指します
つまり、MobStatusのStart()メソッドを実行するコードになります

using UnityEngine;

public class EnemyStatus : MobStatus
{
    protected override void Start()
    {
        base.Start();
        Debug.Log($"{gameObject.name}のEnemyStatus Start");
    }
}

シーン構成

Enemy1ゲームオブジェクト

Enemy2ゲームオブジェクト

実行結果

Enemy1のMobStatus Start
Enemy1のEnemyStatus Start
Enemy2のMobStatus Start
Enemy2のEnemyStatus Start

規定クラスのメソッドが呼ばれ(baseのメソッド)、続いて派生クラスのメソッドが呼ばれています

UML図

クラス図

PlantUML diagram

シーケンス図

EnemyStatusスクリプトの記述変更による実行結果の違い

Startメソッド自体を削除

クラス宣言とMobStatusから継承された派生クラスの宣言のみです

using UnityEngine;

public class EnemyStatus : MobStatus
{
}

基本クラスのStartメソッドだけは実行されます
UnityEngineのコンパイラは、Startメソッドを実行しようとしますが、派生クラスにないので、規定クラスのStartメソッドを見つけて実行するためです

Enemy1のMobStatus Start
Enemy2のMobStatus Start

Startメソッドは記述されているが、空ブロック

Startメソッドが空のブロック

using UnityEngine;

public class EnemyStatus : MobStatus
{
    protected override void Start()
    {
    }
}

base.Startがないので基底クラスのメソッドも呼び出されません

参考

(override)オーバーライドとは

C#における「オーバーライド」は、クラスの継承と多態性を実現するための重要な概念です。オーバーライドとは、親クラス(ベースクラスまたは基底クラスとも呼ばれます)で定義されたメソッド、プロパティ、またはイベントを、派生クラス(サブクラスまたは子クラスとも呼ばれます)で再定義することを意味します。これにより、派生クラスは親クラスのメンバーをカスタマイズし、新しい振る舞いを提供できます。

以下は、C#でオーバーライドを実現するための基本的な構文です:

class 親クラス
{
    public virtual void メソッド名()
    {
        // メソッドの実装
    }
}

class 派生クラス : 親クラス
{
    public override void メソッド名()
    {
        // メソッドの新しい実装
    }
}

この例では、親クラスに virtual キーワードを使用して仮想メソッドを定義し、派生クラスでは override キーワードを使用してそのメソッドを再定義しています。これにより、派生クラスのインスタンスを使用して親クラスのメソッドを呼び出すと、派生クラスの新しい実装が呼び出されます。この仕組みにより、多態性が実現され、プログラムは実行時に正しいメソッドの実装を選択します。

オーバーライドを使用することで、派生クラスは親クラスの振る舞いを拡張、変更、または特殊化することができ、コードの再利用と保守性が向上します。また、多態性により、異なる派生クラスのインスタンスを共通の親クラスの型として扱うことができ、柔軟性が向上します。

PlantUML図

クラス図

@startuml

class MonoBehaviour {
}

class MobStatus {
  + Start()
}

class EnemyStatus {
  + Start()
}

MobStatus --up|> MonoBehaviour
EnemyStatus --up|> MobStatus

@enduml

シーケンス図

@startuml

actor UnityEngine
UnityEngine -> EnemyStatus : Start()

EnemyStatus -> MobStatus : Start()
activate MobStatus

MobStatus --> EnemyStatus : Return
deactivate MobStatus
activate EnemyStatus
EnemyStatus --> UnityEngine : Return
deactivate EnemyStatus

@enduml
@startuml

actor UnityEngine
UnityEngine -> EnemyStatus : Start()
EnemyStatus --> MobStatus : Start()
activate MobStatus

MobStatus --> EnemyStatus : Return
deactivate MobStatus
EnemyStatus --> UnityEngine : Return
deactivate EnemyStatus

@enduml
@startuml

actor UnityEngine
UnityEngine -> EnemyStatus : Start()
activate EnemyStatus

EnemyStatus --> UnityEngine : Return
deactivate MobStatus
deactivate EnemyStatus

@enduml

Unity

Posted by hidepon