【Unity】C#における継承とは?初心者向けに解説
継承とは?
継承は一つのスクリプトを元に新しいスクリプトを作成する事です。
継承ってなんで使うの?
簡単に言うと似たようなスクリプトを書くときに省略でき、一括管理する事ができるからです。
例えばどんな時に継承使う?
例えばドラゴンとかスライムとか敵を複数実装するとして、同じ変数や関数が出てきます。毎回、敵毎にスクリプトを作成してもいいですがそれだと大変ですよね。そこで同じコードint attack = 1;とかvoid Attack(){~}とかは一個のスクリプトに管理させておいて、敵毎に違うコード(例えば攻撃パターンとか)を別で書いてくという事ができるのが継承です。その時に継承元が「親クラス」で継承先を「子クラス」と言います。
例えばMonster_Parentというスクリプトを作成しました。その後にDragon_ChildとSlime_Childというスクリプトを作成し、継承していきます↓
🐱つまり複数の似たようなスクリプトを管理する場合は継承を使うと凄い楽になります。実際に継承していきましょう↓
継承例
今回Enemyクラスを親クラスとしてそこに子クラスとしてSlimeクラスやSkeletonクラスなど様々な種類の敵を実装していくという仮定で行っていきます。スクリプトEnemy(親)とSkelton(子)を二つ作成して以下のようにします。
親クラス例
子クラス例
オブジェクトにアタッチするのは子クラスの方です。実行結果は親クラスのUpdateとStartが実行されます。(子クラスでUPdateとStartをそのまま宣言すると親クラスの方が無効になるので注意)
コード解説
[CustomEditor(typeof(Enemy))]で親クラスのpublicをインスペクタで表示させるようにもしています。[CustomEditor(typeof(Enemy))]はUnityEditor使用時のものなので#if UNITY_EDITOR ~ #endif をつけなければビルド時にエラーを起こします。
子クラスから親クラスの変数を参照するにはhpをpublicにしとかないといけません。
[System.NonSerialized]でインスペクタに表示しないpublicにする事ができます。
base.Attack() ;でメソッドを子クラスから呼び出せます
オーバーライド(要するに上書き)
子クラスで親クラスのコードを変更して独自性を持たせる事ができます。
使い方としてはデフォルトでAttackメソッドを親で書いておいて、敵の種類によって子クラスでAttackメソッドの内容をオーバーライドつまり上書き変更するとかです。
親↓
子↓
親で上書きさせるメソッドにvirtualをつけて子ではoverrideの修飾子をつけます。これで実行結果はAttackOfSkeltonとログに表示されます。オーバーライドしないとそのままNormalAttackと表示されます。
以下は継承で使う汎用コードになります↓
子クラスで親の変数を使うには?
親クラス内でpublicをつければ良いだけです。
// 親クラス
public GameObject gameObject;
// 子クラス
gameObject.SetActive(true);
親の変数を子クラスから変更したい時のスクリプト
例えばキャラのセリフを子クラスから変更したい時
親クラスのコンポーネントを取得するコードは?
例えばCharacterParent(親)とCharacterChild(子)というクラスを用意したとします。characterGameObjectにCharacterChildのスクリプトをアタッチしています。この場合にcharacterGameObjectのharacterChildの親スクリプトを取得したい場合は以下です↓
characterGameObject.GetComponentInParent<CharacterParent>();
子クラスの関数を外部から実行するには?
例えば子クラスを複数用意したとして、外部からその内の一つの子クラスの関数を実行したいとします。その場合子クラスの名前をそれぞれGetComponetで取得する必要があるように思えますが、実は子クラスの名前に関わらず子クラスの関数を実行する事ができます。
- まず親クラス側に空の関数を用意します↓
//親クラス側
public class Parent : MonoBehaviour
{
public virtual void Clicked()
{
//子クラスでオーバーライド
}
}
- 子クラス側でオーバーライド(上書き)する関数を作ります。
//子クラス側
public class Child : Parent
{
public override void Clicked()
{
Debug.Log("クリックした")
}
}
-
あとは親クラス側でClicked()を実行すると"クリックした"とテキスト表示されます。
-
なので全く関係のないオブジェクトから子クラスの関数を実行したい場合には、親クラスのコンポーネントを取得して親クラスのClicked()関数を実行すれば良いです↓
//関係ない外部のオブジェクトから、子クラスの関数を親クラス経由で実行
childGameObject.GetComponentInParent<Parent>().Cliked();
これで"クリックした"とテキスト表示されます。
記事は以上です。お疲れ様でした😌
Discussion