前回、敵機の動きを追加してみました。これから先もいろいろな動きの敵を追加するために、どうするか考えてみましょう。
この場合、2つの方法が考えられます。一つはオブジェクトに何かしらのデータをもたせて、そのデータによって処理を分岐していく方法。もう一つは、動きの種類ごとにクラスを分けていく方法。今回は、クラスを分けていく方法を採りたいと思います。
敵機の動きごとにクラスを分けて実装する
クラスを分ける
まずは、敵機のクラスの基となるクラスを作ります。どんな敵機にも必要な要素は、生成されたらある程度の時間で破棄されること、撃たれたら消滅すること、敵機の向いている方向に進むこと、とします。そのため、Enemy.csを以下のように書き換えます。
using UnityEngine;
public class Enemy : MonoBehaviour
{
//このクラスの変数など
Rigidbody2D rb;
const float speed = 3f;
const int score = 50;
int lifeTime = 0;
void Start()
{
rb = GetComponent<Rigidbody2D>();
rb.linearVelocity = transform.up * speed;
}
// Update is called once per frame
void Update()
{
lifeTime++;
if (lifeTime > 1800) Destroy(gameObject);
if (transform.position.y < -7 || transform.position.y > 7)
{
Destroy(gameObject);
}
}
void OnTriggerEnter2D(Collider2D collision)
{
Destroy(gameObject);
}
}
クラスの継承
クラスを継承する形で、Enemy01.csを作ります。
using UnityEngine;
public class Enemy01 : Enemy
{
public float roll = 0.5f;
public int interval = 10;
void Start()
{
base.Start();
if (transform.position.x > 0) roll = -roll;
}
void Update()
{
base.Update();
if (lifeTime % interval == 0){
transform.Rotate(0f, 0f, roll);
}
rb.linearVelocity = transform.up * speed;
}
}
public class Enemy01 : Enemyとすることで、Enemyクラスを拡張してEnemy01クラスを作ることができます。これをクラスの継承といいます。このようにするとEnemy01クラスは、Enemyクラスの持っている変数や関数などを使うことができるので、Enemyクラスのコードをいちいちコピペする必要がないことです。また、コピペでクラスを増やしていくと、Enemyクラスに変更を加えた場合、コピペした全てのクラスのコードを修正する必要がありますが、継承にしておくとその手間がなくなりますので、効率的です。
base.Start()は、継承基のクラス(この場合、Enemyクラス)のStart関数を呼び出すものです。このように基のクラスの関数を呼び出したいときは、baseクラスを使います。基本的には、baseクラスの関数を呼び出して処理した後に、派生したクラスの処理をする感じですが、そうではない場合もあると思います。今回は、EnemyクラスのStart関数で、リジッドボディコンポーネントを取得した後、Enemy01クラスの処理を入れています。
実は、このままではエラーが出ます。それにはアクセス権の理解が必要です。このままではEnemy01クラスからは、Enemyクラスの変数にアクセスすることが出来ません。継承したクラス(派生したクラス)であっても、継承基のクラスの変数や関数にはアクセスできないようになっているのです。そこで、継承したクラスからはアクセスしてもよいということを明示するためにprotectedキーワードがあります。変数や関数にこれを付けておくと、派生先のクラスからもアクセスできるようになります。(ちなみにpublicキーワードでは、どのクラスからもアクセスできるようになりますが、安全面で課題があると言われるので使用する場合は必要最小限にしましょう)
下のように、派生先からアクセスする必要のある変数や関数にはprotectedを付けます。
using UnityEngine;
public class Enemy : MonoBehaviour
{
//このクラスの変数など
protected Rigidbody2D rb;
protected const float speed = 3f;
protected const int score = 50;
protected int lifeTime = 0;
protected void Start()
{
rb = GetComponent<Rigidbody2D>();
rb.linearVelocity = transform.up * speed;
}
// Update is called once per frame
protected void Update()
{
lifeTime++;
if (lifeTime > 1800) Destroy(gameObject);
if (transform.position.y < -7 || transform.position.y > 7)
{
Destroy(gameObject);
}
}
protected void OnTriggerEnter2D(Collider2D collision)
{
Destroy(gameObject);
}
}
Enemy01.csを見てみると、StartやUpdateに警告が出ています。継承基のクラスと同じ名前の関数があるけどいいの?ってことだそうです。Start関数やUpdate関数の名前を変えるわけにはいかないので、これはこのままで大丈夫です。でも、大丈夫ってことをコンパイラに知らせるために、newキーワードを使います。
using UnityEngine;
public class Enemy01 : Enemy
{
public float roll = 0.5f;
public int interval = 10;
new void Start()
{
base.Start();
if (transform.position.x > 0) roll = -roll;
}
new void Update()
{
base.Update();
if (lifeTime % interval == 0){
transform.Rotate(0f, 0f, roll);
}
rb.linearVelocity = transform.up * speed;
}
}
これで警告が消えました。
プレハブバリアントを作る
新しい敵を追加するには、Enemyプレハブを複製して一部を変えればいいと思います。そういう用途にちょうどいいものがあります。プレハブバリアントです。
Enemyプレハブを右クリックして、 → を選ぶと、Enemyプレハブを基にしたプレハブバリアントができます。
フォルダの

できたEnemy Variantをリネームして、Enemy01にします。このプレハブには、Enemy.csのスクリプトがついていますので、三点マークからコンポーネントを削除してEnemy01.csを付け直します。

Enemy01プレハブの色をSprite Rendererで変更します。赤から黄色に変えました。


ヒエラルキー上のStageManagerオブジェクトのEnemy欄にEnemy01プレハブをセットして実行してみます。

黄色い敵機を出すことができました。道のりは長かったですが、今後の敵機の追加は簡単になったはずです。
今回はここまでです。お疲れ様でした。
コメント