講義メモ 文法編

文法編:「引数のあるコンストラクタ」「インターフェイス」等

引数のあるコンストラクタ

・クラスや構造体において、オブジェクトの生成時に自動的に実行されるのがコンストラクタ
・オブジェクトの生成時にやってほしいことがあれば、自分でコンストラクタを書くことで、オブジェクトの生成時に実行してもらえる
・メソッドと同様に、コンストラクタにも引数を0個以上指定できる
・「new クラス名()」のカッコ内に値や式を指定すると、その数と型に対応するコンストラクタが呼び出される
・例: public クラス名(int i) { Debug.Log(i); } というコンストラクタがあれば、
 クラス名 参照変数 = new クラス名(整数値や整数式); と生成すると呼び出される
・メソッドのオーバーロード(引数の数と型が違えば同名のものを複数定義できる)はコンストラクタも同様
・よって、多数のコンストラクタを呼び出しパターンの分だけ定義しておくことができる
・主に、生成時にデータメンバに与えたい初期値を受け取るコンストラクタを作成することが多い

ミニ演習 mini03031

・Slime0303クラスを定義。データメンバはstring name、int hpとする
・コンストラクタ()ではnameを"名無し"、hpを10で生成
・コンストラクタ(string n)ではnameをn、hpを10で生成
・コンストラクタ(int h)ではnameを"名無し"、hpをhで生成
・コンストラクタ(string n, int h)ではnameをn、hpをhで生成
・名前とhpを表示するshowメソッドをSlime0303クラスに定義して用いよう
・Main側で4パターンを用いてスライム4匹を生成しshowメソッドで表示しよう

作成例

using UnityEngine;
class Slime0303 {
    string name;
    int hp;
    public void show() { //名前とHPを出力
        Debug.Log("名前:" + name + " HP:" + hp);
    }
    public Slime0303() { //デフォルトコンストラクタ
        name = "名無し"; hp = 10;
    }
    public Slime0303(string n) { //コンストラクタ(名前のみ)
        name = n; hp = 10;
    }
    public Slime0303(int h) { //コンストラクタ(hpのみ)
        name = "名無し"; hp = h;
    }
    public Slime0303(string n, int h) { //コンストラクタ(名前とHP)
        name = n; hp = h;
    }
}
public class mini03031 : MonoBehaviour {
    void Start() {
        Slime0303 suralin = new Slime0303();
        suralin.show();
        Slime0303 hoimin = new Slime0303("ホイミン");
        hoimin.show();
        Slime0303 behoimin = new Slime0303(200);
        behoimin.show();
        Slime0303 rimuru = new Slime0303("リムル", 500);
        rimuru.show();
    }
}

引数のあるコンストラクタ:続き

・メソッドの引数の場合と同様にコンストラクタで値のチェックを行うことで、データメンバに不適切な値が格納されることを防ぐこともできる

例:

using UnityEngine;
class Slime0303 {
    string name;
    int hp;
    public void show() { //名前とHPを出力
        Debug.Log("名前:" + name + " HP:" + hp);
    }
    public Slime0303(string n, int h) { //コンストラクタ(名前とHP)
        name = n;
        if (h > 0) { //HPが正の数であれば用いる
            hp = h;
        }
    }
}
public class mini03031 : MonoBehaviour {
    void Start() {
        Slime0303 rimuru = new Slime0303("リムル", -500);
        rimuru.show();
    }
}

ジェネリクスメソッド

・C言語などでは同じ処理内容でも与えるデータの型が違う場合、その違いの数だけ名前が異なる関数(メソッド)を作成する必要がある。
・C#などでは、オーバーロードにより、同じ名前のメソッドにできる
・加えて、型情報を受け取ることができるのがジェネリクスメソッド
・ジェネリクスメソッドはC#やUnityが提供するものもあるが、プログラマが自作することもできる
・型情報を受け取る変数に該当するものが型パラメータで、ジェネリックパラメータともいう
・ジェネリクスメソッドを自作する場合、型パラメータは大文字のTなどを用いることが多い

ジェネリクスメソッドの例:2値の両方を出力するLog2メソッド

・int型用に作ると: public void Log2(int a, int b) { Debug.Log(a); Debug.Log(b); }
・ジェネリクスメソッドにすると
 : public void Log2<T>(T a, T b) { Debug.Log(a); Debug.Log(b); }
・呼び出し方は: Log2<int>(10, 20);
・このまま実数にして: Log2<double>(3.14, 2.12);

提出:ミニ演習 mini03032.cs

・上記のジェネリクスメソッドの例を試すプログラムを作ろう

講義メモ

・p.180「Collider 2Dコンポーネントで衝突判定をする」
・文法編「引数のあるコンストラクタ」「インターフェイス」等

p.180 Collider 2Dコンポーネントで衝突判定をする

・Collider2D:2Dゲームプレイで使用されるコライダー型の親クラス
・p.180下②[Open Prefub]⇒[Open]
・p.181上①「Physics 2D」のクリックは不要で②に進む
・p.181下②[Open Prefub]⇒[Open]
・p.183下①「Box.cs」を作成⇒「Add Component」「New Script」「Box」「Create and add」「:」「Edit Script」

p.183 野菜とBoxの衝突判定のスクリプトを書く:OnTriggerEnter2D

・OnTriggerEnter2D(Collider2D)メソッド:MonoBehaviourクラスからBoxクラスが継承
・オブジェクトにアタッチしたトリガーの中に別のオブジェクトが入ったときに呼び出される。
・入ったオブジェクトに関する詳細な情報は呼び出し時に渡されるCollider2D型の引数に代入される。
・Collider2DクラスはBoxCollider2DクラスとCircleCollider2Dクラスの基本クラスなので、
 どちらの型のオブジェクトも、Collider2D型の引数で扱える

p.184 Box.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI; //Text用

public class Box : MonoBehaviour {
    public Text scoretext; //スコア文字列用のパブリック変数
    int score = 0; //スコア
    void OnTriggerEnter2D(Collider2D other) { //Colliderに呼ばれるメソッド
        Vegetable.Type typeA = GetComponent<Vegetable>().type; //Typeはp.157参照
        Vegetable.Type typeB = other.GetComponent<Vegetable>().type; //相手種別を得る
        if (typeA == typeB) { //種別が一致?
            score++; //スコアアップ
            scoretext.text = score.ToString(); //スコアを文字列化して格納
            Destroy(other.gameObject); //相手を消す
        }
    }
}

p.187 GetComponentメソッドでコンポーネントを取得する

・Vegetable.Type typeA = GetComponent<Vegetable>().type;
・Vegetable.Typeは、p.157「Vegetable.cs」で定義した列挙なのでtypeAは列挙型になる
・GetComponentはジェネリックメソッド(型情報を指定できるメソッド)でMonoBehaviourクラスからBoxクラスが継承
・Transformコンポーネントはtransformプロパティ(p.145)で得られるが、それ以外はこれを用いる
・GetComponentメソッドでは、ジェネリックパラメータにおいて取得したいコンポーネントの型を指定する

・Vegetable.Type typeB = other.GetComponent<Vegetable>().type;
・「other.」は「引数で受け取った相手の」という意味
・GetComponentメソッドは取得失敗時はnull(空)を返すだけでエラー終了はしない

p.189 数を増やしてBoxに入った野菜を削除する

・scoretext.text = score.ToString();
・scoretextはUnityEngine.UI.Textクラスのオブジェクトで、画面上に文字列を表示する仕掛けを提供するもの
・scoretext.textはそのstring型プロパティで表示する文字列そのものを扱う
・ToString()メソッドはC#の全オブジェクトが持つメソッドで、全クラスの暗黙の基本クラスであるobjectクラスのメソッド。
・int型であるscoreは内部的にInt32構造体となっており、この中でToString()メソッドをオーバーライドして
 整数値を文字列に変換して返している
・整数なので文字列に対する2項+演算子で連結しても同じ結果になる

・Destroy(other.gameObject);
・DestroyメソッドはMonoBehaviourクラスからBoxクラスが継承したもの
・otherは引数で受け取った相手(Collider2D型)で、gameObjectプロパティにより、そのGameObjectが得られる

【参考】p.190 C#の命名規約に関して

・一般的にクラス名、メソッド名、列挙名、構造体名などは先頭を大文字にする
・一般的に変数名、プロパティ名などは先頭を小文字にする
・大文字1文字の名前は(ジェネリックの型パラメータを除いて)避けることが多い
・小文字1文字の名前は、使い捨ての変数のみに制限することが多い
 例: for (int i; i < n; i++) のiやn

p.190 野菜の種類と関連するTextを指定する

・p.191②「Text(Regacy)」をBoxの「Scoretext」にドラッグ&ドロップ
・p.191⑤「Text(Regacy)(1)」をBox(1)の「Scoretext」にドラッグ&ドロップ

今週の話題

今回トップも「マリオvs.ドンキーコング(Switch)」GO!
『ダンクロ』不調で3期連続赤字のKLab、EAとの協業で逆転狙う【ゲーム企業の決算を読む】GO!
TGS2024でインディーゲームを無料出展―「Selected Indie 80」出展タイトルを募集中【TGS2024】GO!
『ラグナロク』好調も先細りが懸念材料?ガンホーは北米エリア開拓がカギ【ゲーム企業の決算を読む】GO!
約900名人員削減のSIE、新卒採用ページでメッセージを発信―新卒社員には影響なし GO!

Respawn開発の「スター・ウォーズ」FPSも開発中止に…EA、全従業員の約5%を削減へ GO!
Epic Gamesがハッキングされた疑い―犯人グループが約200GBの内部情報をおさえたと主張 GO!
『ティアキン』違法DLを助長した―ニンテンドースイッチエミュレーター「Yuzu」を任天堂が提訴 GO!

前回のコメント

・マウスなどでの操作のことも分かり、次回以降も楽しみです

 何よりです。

・あまり書いていることは変わらないのに使い道がだいぶ違うことで理解するのに時間がかかるようになってきました

 カリキュラム後半の難度は上がることはあっても下がることはありませんので、
 テキストや講義メモの再確認をしてみてください。

・次回もよろしくお願いします
・次回もよろしくお願いします

 こちらこそ、宜しくお願い致します。

講義メモ

・p.160「shooterにプレハブを渡す」から
・文法編「インターフェイス」

p.160 shooterにプレハブを渡す

・p.161①で表示される画面が変わっており「Size」表記はなくなっている
・InputクラスはUnityEngineに含まれるクラスで入力システムのインターフェースを提供する
 https://docs.unity3d.com/ja/2022.2/ScriptReference/Input.html
・Input.GetMouseButtonUp(int)は、その静的メソッドで、マウスボタンを離したフレームの間だけ trueを返す
・InstantiateメソッドはMonoBehaviourクラスから継承したもので、オブジェクトをクローンする。
 引数はGameObject、Vector3、Quaternionの3つで、対象、位置、回転を示す
・Quaternion.identityは無回転(元のまま)を指す
・Quaternionは四元数ともいい回転を表す手法
・実行してクリックし続けるとHierarchyが生成したオブジェクトの洪水になるが、プレイを停止すると消える

p.162 Shooter.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Shooter : MonoBehaviour {
    float move = 0.05f; //単精度変数を初期化して移動単位とする
    public GameObject[] prefabs = new GameObject[4]; //GameObjectの配列[4]を生成
    void Update() { //フレーム表示ごとに実行する
        Vector3 pos = transform.position; //位置情報を得る
        pos.x += move; //得たX座標に移動単位を足し込む(右移動)
        if (pos.x < -2.5f) { //左端に達した?
            move = 0.05f; //移動単位を正に(次回は右移動に)
        }
        if (pos.x > 2.5f) { //右端に達した?
            move = -0.05f; //移動単位を負に(次回は左移動に)
        }
        transform.position = pos; //位置情報に書き戻す(実際に移動する)
        if (Input.GetMouseButtonUp(0)) { //マウスが左ボタンアップされていたら
            Instantiate(prefabs[0], pos, Quaternion.identity); //要素[0]を生成
        }
    }

    void Start() {

    }
}

p.164 野菜の種類を順番に切り替える

・変数curvageの値を0,1,2,3,0,1,2,3,0,1,2,3,0,… とするのが目的
・curvage++; curvage %= 4; は、if文や条件演算子でも記述できるが、割った余りにする方が安全性が高い
 例①: if (curvage >= 3) curvage = 0; else curvage++;
 例②: curvage = (curvage >= 3) ? 0 : curvage + 1;

p.165 Shooter.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Shooter : MonoBehaviour {
    float move = 0.05f; //単精度変数を初期化して移動単位とする
    public GameObject[] prefabs = new GameObject[4]; //GameObjectの配列[4]を生成
    int curvage = 0; //現在の野菜の添字
    void Update() { //フレーム表示ごとに実行する
        Vector3 pos = transform.position; //位置情報を得る
        pos.x += move; //得たX座標に移動単位を足し込む(右移動)
        if (pos.x < -2.5f) { //左端に達した?
            move = 0.05f; //移動単位を正に(次回は右移動に)
        }
        if (pos.x > 2.5f) { //右端に達した?
            move = -0.05f; //移動単位を負に(次回は左移動に)
        }
        transform.position = pos; //位置情報に書き戻す(実際に移動する)
        if (Input.GetMouseButtonUp(0)) { //マウスが左ボタンアップされていたら
            Instantiate(prefabs[curvage], pos, Quaternion.identity); //現在の野菜を生成
            curvage++; //次の野菜へ
            curvage %= 4; //4で割った余りにすることで4を超えたら1に戻す
        }
    }

    void Start() {

    }
}

p.166 プロパティが返す構造体の値は直接書き換えられない

・「transform.position.x += move;」がエラーになる理由は「transform.position」がプロパティであり、
 変数やオブジェクトではないこと
・「transform.position.x」はプロパティが返すオブジェクトである構造体のデータメンバ
・このオブジェクトには名前がなく一時的な存在なので、そこに含まれるデータメンバは利用はできるが、
 書き換えはできない
・よって、いったん変数で受けると書き換え可能になる
 例: Vector3 work = transform.position; work.x += move;
 例: Vector3 work = transform.position; work.x = 4.0f;

p.172 箱のゲームオブジェクトを作成する

・①[Create]⇒「+」
・②[2D Object][Sprite]⇒[2D Object][Sprites][Square]
・③の名前の変更は、戻ってしまうことがあり、⑤の後でリトライすると良い

p.175 UnityUIのCanvasを配置する

・①[Create]⇒「+」

p.176 数を表示するためのTextを配置する

・①[Create]⇒「+」
・②[UI][Text]⇒「UI」「Legacy」「Text」
・p.177上の図「Textが配置されます」⇒「Text(Legacy)が配置されます」
・p.177下の図「Textを移動」⇒「Text(Legacy)を移動し上下に広げる」
 ※位置はp.178上の図のように箱よりも上にする
・また、ここで「Canvas Rendarer」の「Cull Transparent Mes」のチェックをオフにする
・p.178の④まで終えたら、「Scene」を「Game」に切り替えることで設定結果が確認できる

p.178 ゲームオブジェクトを複製する

・①「Textを右クリック」⇒「Text(Legacy)を右クリック」
・p.179上の図「Text(1)」⇒「Text(Legacy)(1)」

文法編「クラスと構造体」「コンストラクタ」「インターフェイス」

p.168 クラスと構造体の違いは

・クラスから生成されたインスタンス=クラスを型とする変数
 例: Slime suralin = new Slime();
・クラスを型とする変数は参照型であり、変数名が持つのは実体ではなく実体の位置情報に該当する
・よって、クラスを型とする変数間で代入すると、位置情報がコピーされ、実体は1つのままで、2つの変数名で扱われる
・つまり、2つ目の変数名は別名のように扱われる
 例: Slime suralin = new Slime(); Slime betumei = suralin; //実体はコピーされない
・よって、複雑で大きなクラスのオブジェクトを「場所を教えるから、そっちでも扱ってくれ」という場合に便利

ミニ演習 mini168

・int型のhpとmpを持つSlimeクラスを定義する(public指定にする)
・Startメソッドの中でSlimeクラス型の変数suralinとhoiminを生成する
・suralin.hpに10、hoimin.hpに20を代入
・Slimeクラス型の配列slimesを作り、suralinとhoiminを要素にする
 Slime[] slimes = { suralin, hoimin };
・slimes[0].hpと、slimes[1].hpをDebug.Logで出力
・slimes[0].hpと、slimes[1].hpの値を交換する
・suralin.hp、hoimin.hpをDebug.Logで出力

作成例

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
class Slime168 { //スライムクラス
    public int hp;
    public int mp;
}
public class mini168 : MonoBehaviour{
    void Start() {
        Slime168 suralin = new Slime168(); //スライムオブジェクトを生成
        Slime168 hoimin = new Slime168(); //スライムオブジェクトを生成
        suralin.hp = 10;
        hoimin.hp = 20;
        Slime168[] slimes = { suralin, hoimin }; //配列に格納
        Debug.Log("slimes[0].hp = " + slimes[0].hp + " [1].hp = " + slimes[1].hp);
        var work = slimes[0].hp;
        slimes[0].hp = slimes[1].hp; //配列側で2匹のhpを交換
        slimes[1].hp = work;
        Debug.Log("suralin.hp = " + suralin.hp + " hoimin.hp = " + hoimin.hp); //元も交換されている
    }
}

ミニ演習 mini169

・Slime169構造体にして、同様の処理を行って、結果を確認しよう

作成例

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
struct Slime169 { //スライム構造体
    public int hp;
    public int mp;
}
public class mini169 : MonoBehaviour {
    void Start() {
        Slime169 suralin = new Slime169(); //スライムオブジェクトを生成
        Slime169 hoimin = new Slime169(); //スライムオブジェクトを生成
        suralin.hp = 10;
        hoimin.hp = 20;
        Slime169[] slimes = { suralin, hoimin }; //構造体配列に格納(Copyになる)
        Debug.Log("slimes[0].hp = " + slimes[0].hp + " [1].hp = " + slimes[1].hp);
        var work = slimes[0].hp;
        slimes[0].hp = slimes[1].hp; //配列側で2匹のhpを交換
        slimes[1].hp = work;
        Debug.Log("suralin.hp = " + suralin.hp + " hoimin.hp = " + hoimin.hp); //元は変わらない
    }
}

文法編:コンストラクタ

・クラスや構造体において、オブジェクトの生成時に自動的に実行されるのがコンストラクタ
・コンストラクタはシステムが空で用意してくれるので、意識しなくても良い
・しかし、オブジェクトの生成時にやってほしいことがあれば、自分でコンストラクタを書くことで、オブジェクトの生成時に実行してもらえる
・つまり、コンストラクタは一種のメソッドだが、名前はなく、クラス名が名前になる
・例:
 class Slime170 {
  public Slime170() { Debug.Log("OK"); } //コンストラクタ
  }

ミニ演習 mini170

・上記のSlime170クラスのインスタンスを生成するとコンストラクタが動作することを確認しよう

作成例

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
class Slime170 {
    public Slime170() { Debug.Log("OK"); } //コンストラクタ
}
public class mini170 : MonoBehaviour {
    void Start() {
        Slime170 suralin = new Slime170(); //生成するとコンストラクタが動作する
    }
}

文法編:デフォルトコンストラクタ

・インスタンス生成時に引数を指定しないときに動作するコンストラクタをデフォルトコンストラクタという
・主に、引数のないコンストラクタが該当する
・なお、構造体では引数のないコンストラクタはシステムが用意し、自前の定義はエラーになる

提出:ミニ演習 mini170

今週の話題

今回トップは「マリオvs.ドンキーコング(Switch)」GO!
Aiming、コロプラとの資本業務提携で16.4億円の資金調達―新規オンラインゲーム共同開発など目指す GO!
「INDIE Live Expo」2024年5月25日に開催決定ー出展エントリーは3月12日まで GO!
「PlayStation VR2(PS VR2)」が2024年内にPCでも利用可能になるとソニーがひっそり発表 GO!

「子供がプロeスポーツチームにスカウトされた」との問い合わせ相次ぐ…チームは“詐欺行為”の可能性があると注意喚起 GO!

前回のコメント

・ゲーム内オブジェクトが増えてきてゲーム画面に近づいてきていて楽しいです

 何よりです。

・unity側の機能として物理演算などを解決できるのは便利でいいなと感じました

 ですね。まさに「楽」です。

・次回もよろしくお願いします
・次回もよろしくお願いします

 こちらこそ宜しくお願い致します。

講義メモ:文法編

【文法編】抽象クラス(準備)

・以前作成した mini133.cs を用いる

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
class Slime { //スライムクラスの定義(mini133クラスが利用する部品クラス)
    public int hp; //HP
    public string name; //名前
    public virtual void show() { //名前とHPを出力するメソッド(オーバーライド可)
        Debug.Log("名前:" + name + ",HP:" + hp);
    }
}
class HoimiSlime : Slime { //ホイミスライムクラスの定義(スライムを継承)
    // public int hp; //HPが継承される
    // public string name; //名前が継承される
    // public void show() { //名前とHPを出力するメソッドが継承される
    //  Debug.Log("名前:" + name + ",HP:" + hp);
    // }
    public int mp; //MPを追加
    public override void show() { //名前とHPとMPを出力するメソッドにしてオーバーライド
        Debug.Log("名前:" + name + ",HP:" + hp + ",MP:" + mp);
    }
}
public class mini133 : MonoBehaviour { //Unityでの実行用クラス
    void Start() { //Unityシステムから開始時に呼び出されるメソッド
        Slime Rimuru = new Slime(); //スライムクラスからオブジェクトを生成
        Rimuru.hp = 100; //HPをセット
        Rimuru.name = "リムル"; //名前をセット
        Rimuru.show(); //名前とHPを出力するメソッドを呼ぶ

        HoimiSlime Hoimin = new HoimiSlime(); //ホイミスライムクラスからオブジェクトを生成
        Hoimin.hp = 10; //HPをセット
        Hoimin.mp = 500; //HPをセット
        Hoimin.name = "ホイミン"; //名前をセット
        Hoimin.show(); //名前とHPとMPを出力するメソッドを呼ぶ

        Slime[] slimes = { Rimuru, Hoimin }; //スライムの配列に格納する
        slimes[0].show(); //[0]であるRimuruの名前とHPを表示
        slimes[1].show(); //[1]であるHoiminの名前とHPを表示
    }
    void Update() {

    }
}

【文法編】抽象クラス

・多くのクラスの基本クラスとなるクラスを設計すると「具体的なことは派生クラスで決める」場合が増える
・また「車」や「家」では実体が作れないように、基本クラスはインスタンスの生成には向かなくなる
・このような場合、基本クラスを抽象クラスとして作っておけば良い
・書式: abstract class クラス名 {…}

アレンジ演習:mini133.cs

・Slimeクラスの基本クラスとして、Monsterという抽象クラスを定義しよう

作成例

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
abstract class Monsters { } //【追加】抽象クラスであるモンスタークラス
class Slime : Monsters { //【変更】スライムクラスの定義(モンスターを継承)
    public int hp; //HP
    public string name; //名前
    public virtual void show() { //名前とHPを出力するメソッド(オーバーライド可)
        Debug.Log("名前:" + name + ",HP:" + hp);
    }
}
class HoimiSlime : Slime { //ホイミスライムクラスの定義(スライムを継承)
    // public int hp; //HPが継承される
    // public string name; //名前が継承される
    // public void show() { //名前とHPを出力するメソッドが継承される
    //  Debug.Log("名前:" + name + ",HP:" + hp);
    // }
    public int mp; //MPを追加
    public override void show() { //名前とHPとMPを出力するメソッドにしてオーバーライド
        Debug.Log("名前:" + name + ",HP:" + hp + ",MP:" + mp);
    }
}
public class mini133 : MonoBehaviour { //Unityでの実行用クラス
    void Start() { //Unityシステムから開始時に呼び出されるメソッド
        Slime Rimuru = new Slime(); //スライムクラスからオブジェクトを生成
        Rimuru.hp = 100; //HPをセット
        Rimuru.name = "リムル"; //名前をセット
        Rimuru.show(); //名前とHPを出力するメソッドを呼ぶ

        HoimiSlime Hoimin = new HoimiSlime(); //ホイミスライムクラスからオブジェクトを生成
        Hoimin.hp = 10; //HPをセット
        Hoimin.mp = 500; //HPをセット
        Hoimin.name = "ホイミン"; //名前をセット
        Hoimin.show(); //名前とHPとMPを出力するメソッドを呼ぶ

        Slime[] slimes = { Rimuru, Hoimin }; //スライムの配列に格納する
        slimes[0].show(); //[0]であるRimuruの名前とHPを表示
        slimes[1].show(); //[1]であるHoiminの名前とHPを表示
    }
    void Update() {

    }
}

【文法編】抽象クラスの抽象メソッド

・抽象クラスには名前だけのメソッドを定義できる
・これにより「わが一族であれば、このメソッドを持つべきだ」というルールを設定して、派生クラスに守らせることができる
・また、派生クラスを利用する側も「この抽象クラスの派生クラスだから、このメソッドがあるはず」と理解できる
・例: Monstersクラスの一族はshowメソッドを持つこと
・書式: public abstract 戻り値型 メソッド名(引数リスト); //中カッコの代わりにセミコロン

提出:アレンジ演習:mini133.cs

・Monstersクラスに抽象メソッドpublic abstract void show(); を追記しよう
・Slimeクラスではこのメソッドをオーバーライドしよう