講義メモ ・ゲーム開発編:p.183「野菜とBoxの衝突判定のスクリプトを書く」から ・文法編:ジェネリクス など ゲーム開発編:p.183「野菜とBoxの衝突判定のスクリプトを書く」 p.184 Box.cs using UnityEngine; using UnityEngine.UI; //UnityUIのText用 public class Box : MonoBehaviour { public Text scoretext; //UnityUIが提供するTextクラスを型とするパブリック変数 int score = 0; //スコアを扱うインスタンス変数を0で初期化 private void OnTriggerEnter2D(Collider2D other) { //野菜とボックスの衝突時に呼び出されるメソッド Vegetable.Type typeA = GetComponent().type; //ボックスの種類を得る Vegetable.Type typeB = other.GetComponent().type; //野菜の種類を得る if (typeA == typeB) { //得た野菜型が等しい=野菜とボックスが一致? score++; //スコアをインクリメント scoretext.text = score.ToString(); //整数値を文字列化してTextオブジェクトに与える Destroy(other.gameObject); //野菜オブジェクトを破棄することで消す } } } p.186 野菜とBoxの衝突判定のスクリプトを書く:OnTriggerEnter2Dメソッドについて ・BoxCollider2Dを設定してあるオブジェクトにおいて、このメソッドを実装することで、Unity側でオブジェクトの衝突を検知して呼び出してもらえる ・この考え方はイベントリスナーとして汎用的に扱われており、言語やゲームエンジンによって実装方法や内部仕様が異なる。 ・Unityの場合「OnTrigger●」と「OnCollision●」があり、トリガーモードかどうかで使い分ける。 ・トリガーモード(p.182)は衝突時に跳ね返らないモードで、これをオンにすることで、衝突後に通過や破棄(画面から消す)したい場合に用いる。 ・また、「OnTrigger●」には「OnTriggerEnter」「OnTriggerExit」「OnTriggerStay」があり、それぞれ、衝突時、衝突終了時、衝突中に対応して動作する p.187 GetComponentメソッドでコンポーネントを取得する ・MonoBehaviourから継承したGetComponentメソッドを実行することで、自分自身や他のMonoBehaviour派生クラスオブジェクトのコンポーネントを取得できる ・GetComponentメソッドは型情報を引数(型パラメータ)として得ることができるジェネリクスメソッド(詳細は後述)なので、今回はVegetableを型パラメータに指定している。 ・GetComponentメソッドで、Vegetableクラスオブジェクトが得られるので、その中で定義しているType型の変数typeを「.type」で得ることができる ・Type型は列挙型で野菜の種類を示すので、Tomato, Gpepper, Broccoli, Potatoのどれかになり、Vegetable.Type型の変数typeAに代入される ・これが、ボックスの種類(どの野菜か)を得ることになる ・OnTriggerEnter2DメソッドのCollider2D型の引数otherには、衝突相手である野菜が得られる ・よって、other.GetComponentメソッドで、同様の手順で野菜の種類が得られ、Vegetable.Type型の変数typeBに代入される p.189 GetComponentメソッドでコンポーネントを取得する:補足:ドット演算子 ・「other.GetComponent().type」のように、ドットで「の」「に所属する」などを連続して表現できる ・複雑で可読性が下がると思われる場合は中間結果を変数に置くことで複数行に分割するとよい 例:  Vegetable.Type typeB = other.GetComponent().type;  ↓  Vegetable work = other.GetComponent(); //①まず野菜オブジェクトを得る  Vegetable.Type typeB = work.type; //②それから中にあるtypeを得る p.189 GetComponentメソッドでコンポーネントを取得する:補足:null ・GetComponentメソッドがオブジェクトを得られなかった場合、異常終了せずに、nullが返される ・nullは無を意味するキーワードで、全ての参照型に対応できる特殊な値。 ・よって「参照型の変数 == null」というような比較が型に限定されずに可能 ・なお、int型などの値型や、Vector3などの構造体型は、nullの代入や比較は不可 p.189 数を増やしてBoxに入った野菜を削除する:補足:スコア処理 ・scoretextは、UnityUIが提供するTextクラスを型とするパブリック変数 ・Textクラスには描画用の文字列を保持するstring型のインスタンス変数textが定義されている ・ここに文字列を代入することで、自動的に画面上に反映する(Unityが制御してくれる) ・スコアを持つ変数scoreはint型なので、string型にするためにToString()メソッドを用いている ・これは「"" + score」としてもOK p.189 数を増やしてBoxに入った野菜を削除する:補足:Destory ・MonoBehaviourクラスから継承されているDestory()メソッドに、ゲームオブジェクトを引数として渡すことで、ゲームオブジェクトを破棄できる ・OnTriggerEnter2DメソッドのCollider2D型の引数otherに対してgameObjectプロパティを指定することで、これに含まれるゲームオブジェクトを得ることができる ・よって、other.gameObjectをDestory()メソッドに渡せば、一致するボックスに衝突してきた野菜がオブジェクトの破棄により画面から消える p.191 野菜の種類と関連するTextを指定する:補足 ・② 1つめのText(Regacy)を[Scoretext]にドラッグ&ドロップ p.192 壁のプレハブを作成する:補足 ①Hierarchyの「+」をクリック ②[2D Object][Sprites][Square] ③名前を「Wall」に変更 ④[Sprite]に「Wall_0」を設定 ⑤[Add Component][Pysics 2D][BoxCollider 2D] ⑥[Size]の[X]を「0.7」に変更 ⑦「Wall」を[Project]にドラッグ&ドロップ ⑧Hierarchyの「Wall」をクリックしDeleteキーで消す p.193 スクリプトを使って壁を配置する:補足 ①Hierarchyの「+」をクリックし[Create Empty]をクリック ②名前を「GameManager」に変更 ③[Add Component][New Script]で「Manager」と入力し[Create and add][:][Edit Script] p.193 スクリプトを使って壁を配置する:補足:Manager.csについて ・ゲームを構成するオブジェクトに所属しないプログラム(スクリプト)であり、別途、GameManagerと名付けたゲームオブジェクトを用意して配置している ・このプログラム(スクリプト)をゲーム開始時に実行し、インスタンスを生成して利用するためにパブリック変数wallpfb(壁のプレハブ)を定義している p.194-195 Manager.cs using UnityEngine; public class Manager : MonoBehaviour { public GameObject wallpfb; //壁のプレハブになるゲームオブジェクトのパブリック変数 void Start() { for (int x = 0; x < 5; x++) { //X(横)方向に5回繰返す for (int y = 0; y < 4; y++) { //Y(縦)方向に4回繰返す Vector3 pos = new Vector3(); //座標指定用の構造体オブジェクトを用意 pos.x = x * 1.2f - 2.4f; //X座標を繰り返しカウンタから得る pos.y = 2.5f - y; //Y座標を繰り返しカウンタから得る Instantiate(wallpfb, pos, Quaternion.identity); //ゲームオブジェクトと座標を指定してインスタンス生成 } } } } p.194-195 Manager.cs:補足 ・座標指定用のVector3構造体オブジェクトを用意している:p.168参照 ・Instantiateメソッドはp.163参照 ・Quaternion.identityプロパティはp.163-164参照。無回転の意味。 p.198 スクリプトを使ってWallを回転させる:補足 ②[Open]をクリック ③[Add Component][New Script]で「Wall」と入力し[Create and add][:][Edit Script] p.199 Wall.cs:補足 ・メソッドの引数として渡すオブジェクトには名前がなくても構わない ・よって、引数の指定場所においてオブジェクトを生成して渡している ・つまり:下記のように2行を1行にし、使い捨てになる変数を省略している  transform.Rotate(new Vector3(0, 0, -5));  ↑  Vector3 work = new Vector3(0, 0, -5);  transform.Rotate(work); ・なお、使い捨てになる変数はできる限り(可読性を下げない限り)定義しないことが望ましい ・RotateはTransformクラスのメソッドで、Vector3構造体型のオブジェクトを渡すことで、ゲームオブジェクトを回転させることができる ・なお、6種類のオーバーロードがあり、回転方法を都合に合わせて指定できる p.200 回転方向を切り替える Wall.cs:補足 ・clockwiseはbool型の変数で、true/falseのみを保持でき、時計回り/反時計回りを意味している ・bool型の変数は、if/whileなどの条件にそのまま指定できる p.201 Wall.cs using UnityEngine; public class Wall : MonoBehaviour { public bool clockwise = true; //時計回りを意味するパブリック変数 void Update() { if (clockwise) { //時計回り? transform.Rotate(new Vector3(0, 0, -5)); //ゲームオブジェクトを座標指定により回転 } else { //反時計回り? transform.Rotate(new Vector3(0, 0, 5)); //ゲームオブジェクトを座標指定により回転 } } } p.202 Manager.cs using UnityEngine; public class Manager : MonoBehaviour { public GameObject wallpfb; //壁のプレハブになるゲームオブジェクトのパブリック変数 void Start() { for (int x = 0; x < 5; x++) { //X(横)方向に5回繰返す for (int y = 0; y < 4; y++) { //Y(縦)方向に4回繰返す Vector3 pos = new Vector3(); //座標指定用の構造体オブジェクトを用意 pos.x = x * 1.2f - 2.4f; //X座標を繰り返しカウンタから得る pos.y = 2.5f - y; //Y座標を繰り返しカウンタから得る GameObject obj = Instantiate(wallpfb, pos, Quaternion.identity); //ゲームオブジェクトと座標を指定してインスタンス生成 Wall wall = obj.GetComponent(); //壁プレハブからゲームオブジェクトを得る if (y % 2 == 0) { //Y(縦)方向で偶数番目? wall.clockwise = true; //時計回りにする } else { wall.clockwise = false; //反時計回りにする } } } } } p.205 ゲーム画面の底を作成する 前半 ①Hierarchyの「+」をクリックし[2D Object][Sprites][Square]をクリック ②名前を「Bottom」に変更 ③[Position]のXを「0」Yを「-6」に変更し、[SpriteRenderer]の[Sprite]を「Background」にする. ※下から7個目にある p.205 ゲーム画面の底を作成する 後半 ①[Add Component][Physics 2D][BoxCollider 2D]を追加 ②[Is Trigger]をクリックしてチェックをオンにする p.206 ゲーム画面の底を作成する 前半 ①[Transform]の[Scale]のXを「100」Yを「4」に変更 ※ここでScene上でCtrlキーを押しながらマウスホイールを手前に回すことで表示を縮小すると下の方に「底」が見えてくる p.206「ゲーム画面の底を作成する 後半 ①[Add Component][New Script]で「Bottom」と入力し[Create and add][:][Edit Script] p.206 Bottom.cs using UnityEngine; public class Bottom : MonoBehaviour { private void OnTriggerEnter2D(Collider2D other) { //衝突したら Destroy(other.gameObject); //何であろうと破棄(消去)する } } 提出:p.206 Bottom.cs 次回(最終回)予告 ・文法編:ジェネリクス、ToStringメソッド など ・ゲーム開発編:特別編「3D迷路&シューティングゲーム開発演習」