講義メモ:ゲーム開発編

ゲーム開発編:p.134 スマートフォン向けの画面にする:プロジェクトを作成

・Unityのバージョンアップにより、手順が変わっている
・まず、Unity Editorを閉じてUnity Hubに戻り:
① エディターのバージョンを6000.0.xにしてから「New Project」
②「2D(Build-In Render Pipeline)」を選択
③ プロジェクト名(例:furiCSharpGame)、保存場所を指定
④「Unity Cloudに接続」はオフにする
⑤「プロジェクトを作成」
⑥「… at my own risk」

ゲーム開発編:p.134 スマートフォン向けの画面にする:スマートフォンの画面サイズに合わせる

・テキストp.135の手順①~⑤を実行
・シーンのサイズが変わっていないようにみえるが、これはスケールが大きいままのため
・よって、Projectの高さを減らしてから、Scaleのスライダーを左端まで下げると良い

ゲーム開発編:p.136 ゲームで使用する画像を用意する

・p.136① [Project]タブをクリックし「+」をクリック
 ※ Unity6から「InputSystem_Actions」が自動生成されるようになっているが無視してOK
・テキストp.136の手順②~③を実行
・それから、Imagesフォルダをダブルクリックして開いておく

ゲーム開発編:p.136 ゲームで使用する画像を用意する:画像ファイルを取り込む

・用いる画像はダウンロードした「furiCSharp_sample」の中の「gameimage」フォルダにある
・全10ファイルをUnityのImagesフォルダにドラッグ&ドロップする

ゲーム開発編:p.139 プレイヤーキャラクターを出現させる

・①「Hierachy」の「+」をクリック
・②「2D Object」「Sprites」「Square」
・テキストp.139の手順③を実行

ゲーム開発編:p.140 プレイヤーキャラクターを出現させる つづき

・①「Sprite」の「Square」の右の「〇の中に・」をクリック
・②「Shooter_0」をダブルクリック

ゲーム開発編:p.141 座標を指定してShooterを移動する

・①[Transform]の[Position]の[X]を0に、[Y]を4にする

ゲーム開発編:p.141 スクリプトを使ってShooterを動かす

・p.142①「Add Component」「New Script」で「shooter」と入力しEnter
・「:」右クリックで「Edit Script」

p.142 Shooter.cs

using UnityEngine;
public class shooter : MonoBehaviour {
    float move = 0.05f; //単精度実数型のフィールド変数moveの初期化
    void Update()    {
        Vector3 pos = transform.position; //構造体Vector3のオブジェクトposをプロパティを利して生成
        pos.x += move; //オブジェクトposの持つ変数xにmoveの値を足し込む
        transform.position = pos; //オブジェクトposをtransformプロパティに渡すと画面に反映
    }
}

文法編:構造体

・構造体はC言語に元々ある仕組みで、複数の変数をグループ化して扱う手法
・なお、複数の同じ型と意味の変数をグループ化するのが配列、型や意味が異なる変数をグループ化するのが構造体
・Vector3構造体の場合、3次元データを表す3つの変数x、y、zをグループ化して扱うためなどに用いる
・構造体はintなどと同様にデータ型として利用できる(クラスにおける変数と同様)
・C#では、C言語で書かれたプログラムの移植時に、クラスにすると効率が落ちるのを避けるために「軽量クラス」として
 「C#の構造体」が利用可能
・よって、C言語の構造体とは異なり、「C#の構造体」ではデータ以外にメソッドなども記述でき、
 継承を行わないクラスなどで用いることが多い
・Vector3構造体はUnityが提供するものだが、プログラマが自前の構造体を定義して用いることも可能
・書式例: struct 構造体名 { 定義内容 }
・構造体もクラスと同様に、構造体名を型とするオブジェクト名を定義してオブジェクトを生成して用いる

作成例 ex0727b

using UnityEngine;
public class ex0727b : MonoBehaviour{
    struct Map { //2D座標の構造体の定義
        public int x; //Map構造体の持つデータ
        public int y; //同上
    } 
    void Start()    {
        Map player = new Map(); //Mapオブジェクトplayerを生成
        player.x = 100; //playerが持つ変数xに代入(プレイヤーのX座標を設定)
        player.y = 200; //playerが持つ変数yに代入(プレイヤーのY座標を設定)
        Debug.Log(player.x + ", " + player.y);  //playerが持つ変数の値を出力
    }
}

提出:文法編:構造体の作成例 ex0727b

講義メモ Chapter 4

p.129 Chapter 4 ゲームオブジェクトを動かそう

p.131 最初からある2つのメソッドの役割

・メソッドの定義の冒頭に記述する「戻り値型」で、戻り値がない場合は「void」を指定
・なお、void指定時はメソッド内で「return ●」は指定不可だがメソッドを脱出して呼び出し元に戻る「return」は可能。
・ちなみに、void以外を指定時は、内部でどう分岐しても、必ず最後に「return ●」する必要がある
・Unityが用意してくれるStart()はC#のメソッドの仕組みをUnityが拡張したもので、C#のメソッドとは文法的に異なるため、
 メッセージというUnity独自の仕組みに分類される(p.133下4行)
・Update()も同様で、テキストでは便宜的にメソッドと呼んでいるので注意。
・また、p.131に「新しいメソッドを作るための書き方」とあるが、Start()とUpdate()の場合、
 Unityが提供してくれる仕組みへの加筆に該当するので、C#における「新しいメソッドを作るための書き方」とは異なる
・この仕組みにより、Start()に記述した内容は起動時に1回だけ、Update()に記述した内容は起動後一定時間おきにUnityにより
 実行される
・よって、Start()に記述するのは「ゲームの初期処理」Update()に記述するのは「ゲームの主処理」となることが多い

p.132 クラスの作り方を見直してみよう

・継承(インヘリタンス)とは、あらかじめあるクラスの構成要素(メンバ)を引き継いでクラスを作ること
・これにより、Unityのようなシステムが用意した仕掛けがあるクラスを継承し、必要なことを書き足すだけで動作する
 プログラム(クラス)を作成できる
・例えば、Unityの場合、MonoBehaviourクラスが提供されていて、これを継承し、Startメソッドの内容を記述するだけで、
 Unity上で動作するプログラムになる
※この考え方を差分プログラミングという
・なお、プログラマが自らクラスを作成し、これを継承することができるので、複数のクラスが継承するクラスを記述することで
 共通化や部品化が可能になる
※継承されるクラスを基本クラス(基底クラス、親クラスなど)、継承するクラスを派生クラス(子クラスなど)という
・基本クラスを書き換えると、派生クラスに継承される内容は自動更新されるので、修正の反映モレを防ぎ、部品化の効率を
 上げられる
・クラスのメンバにはメソッドのみならず、データなども記述できる(例:パブリック変数)

ここからの進め方

・ゲーム開発編と文法編にプロジェクトを分けて進めます
・ゲーム開発編としては、p.134からの手順で「furiCSharpGame(例)」プロジェクトを作成して2Dゲームを段階的に作成
・文法編としては、現在利用しているプロジェクトにゲームオブジェクトGameObject4を作成して文法に関わるプログラムを都度作成

文法編:クラスの継承

・C#ではクラス内にクラス(インナークラス)を作成し、そのクラス内でのみ利用可能にできる
・よって、テストや確認にも便利
・Unityの環境ではMonoBehaviourクラスの派生クラスのみが実行可能なため、自前のクラスを作成する代わりに、
 MonoBehaviourクラスの派生クラスの中にインナークラスを作成しよう

文法編:データのみを持つインナークラス Monster を作る ex0727a.cs

・データとしてint型のhpとmpを持つ
・書式例: public 型 変数名;
・Start()の中で、newによりMonsterクラスのオブジェクトを生成する
・書式例: クラス名 オブジェクト名 = new クラス名();
・すると、オブジェクト名.変数名 が確保されて利用可能になる

作成例

using UnityEngine;
public class ex0727a : MonoBehaviour{
    class Monster { //インナークラスMonsterの定義
        public int hp; //Monsterクラスの持つデータ
        public int mp; //同上
    } 
    void Start()    {
        Monster hachi = new Monster(); //Monsterオブジェクトhachiを生成
        hachi.hp = 100; //hachiが持つ変数hpに代入
        hachi.mp = 200; //hachiが持つ変数mpに代入
        Debug.Log(hachi.hp + ", " + hachi.mp);  //hachiが持つ変数の値を出力
    }
}

文法編:インナークラス Monster にメソッドを作る ex0727a.cs

・UnityのStart()に近い形で、インナークラスの中に処理を行うメソッドを記述できる
・書式例: public void メソッド名() { 処理内容 }
・すると、オブジェクト名.メソッド名()で実行可能になる

作成例

using UnityEngine;
public class ex0727a : MonoBehaviour{
    class Monster { //インナークラスMonsterの定義
        public int hp; //Monsterクラスの持つデータ
        public int mp; //同上
        public void show() { //Monsterクラスの持つメソッド
            Debug.Log(hp + ", " + mp);  //2変数の値を出力
        }
    }
    void Start()    {
        Monster hachi = new Monster(); //Monsterオブジェクトhachiを生成
        hachi.hp = 100; //hachiが持つ変数hpに代入
        hachi.mp = 200; //hachiが持つ変数mpに代入
        hachi.show();  //hachiが持つメソッドの実行
    }
}

文法編:インナークラス Monster を継承する Slimeクラスを作る ex0727a.cs

・「class クラス名 : MonoBehaviour」と同様に、インナークラス SlimeをMonsterを継承して定義できる
・すると、Monsterクラスに定義されているデータやメソッドが自動的に引き継がれる
・そして、Slimeクラス独自のデータやメソッドを書き加えることができる

作成例

using UnityEngine;
public class ex0727a : MonoBehaviour{
    class Monster { //インナークラスMonsterの定義
        public int hp; //Monsterクラスの持つデータ
        public int mp; //同上
        public void show() { //Monsterクラスの持つメソッド
            Debug.Log(hp + ", " + mp);  //2変数の値を出力
        }
    } 
    class Slime : Monster { //Monsterを継承するクラスSlimeの定義
        // ここに public int hp; が継承される
        // ここに public int mp; が継承される
        public string name;
        // ここに public void show() が継承される
    }
    void Start()    {
        Monster hachi = new Monster(); //Monsterオブジェクトhachiを生成
        hachi.hp = 100; //hachiが持つ変数hpに代入
        hachi.mp = 200; //hachiが持つ変数mpに代入
        hachi.show();  //hachiが持つメソッドの実行
        Slime slalin = new Slime(); //Slimeオブジェクトslalinを生成
        slalin.hp = 50; //slalinが持つ継承された変数hpに代入
        slalin.mp = 60; //slalinが持つ継承された変数mpに代入
        slalin.show();  //slalinが持つ継承されたメソッドの実行
        slalin.name = "すらりん"; //slalinが持つSlime独自の変数に代入
        Debug.Log(slalin.hp + ", " + slalin.mp + ", " + slalin.name);  //slalinが持つ変数の値を出力
    }
}

講義メモ

・p.129「Chapter 4 ゲームオブジェクトを動かそう」から

提出:ミニ演習 mini0720b.cs

・上記のジャグ配列studentsの全要素を添字と共に表示しよう
・forの2重ループにすると良い
・Lengthを活用しよう

作成例

using UnityEngine;
public class mini0720b : MonoBehaviour {
    void Start() {
        int[][] students = new int[3][]; //3年分を確保する
        students[0] = new int[] { 11, 12 }; //1年の2クラス分を生成
        students[1] = new int[] { 21, 22, 23 }; //2年の3クラス分を生成
        students[2] = new int[] { 31, 32 }; //3年の2クラス分を生成
        for (int i = 0; i < students.Length; i++) { 
            for (int j = 0; j < students[i].Length; j++) {
                Debug.Log("[" + i + "][" + j + "] = " + students[i][j]);
            }
        }
    }
}

参考:添字の表示が不要であれば、foreachの2重ループでもOK

using UnityEngine;
public class mini0720b : MonoBehaviour {
    void Start() {
        int[][] students = new int[3][]; //3年分を確保する
        students[0] = new int[] { 11, 12 }; //1年の2クラス分を生成
        students[1] = new int[] { 21, 22, 23 }; //2年の3クラス分を生成
        students[2] = new int[] { 31, 32 }; //3年の2クラス分を生成
        foreach (var w in students) { //wはint[3]型になる
            foreach (var x in w) { //xはint型になる
                Debug.Log(x);
            }
        }
    }
}

補足:パブリック変数の配列

・Unity環境では、パブリック変数として配列を定義できる
・すると、要素数の分だけ、入力領域が用意されるので、要素数が大きい場合には向かない
・なお、パブリック変数の定義において、生成まで行っておく必要がある
・書式: public 型[] 配列名 = new 型[要素数];
・Unity側では配列名でグルーピングされたElements0~要素数-1として表される
・なお、多次元配列には対応していない(定義できるがUnity側では操作できない)

今週の話題

ゲームソフト販売本数ランキング:今週1位も「マリオカート ワールド(Switch2)」 GO!
SIEがPlayStation Studiosタイトルのマルチプラットフォーム展開を推進か?米国向け求人で担当者募集中 GO!
バンダイナムコとソニーが戦略的なパートナーシップを締結!マンガ・アニメなど幅広い領域での協業に取り組む GO!
ゲーム業界の平均年収ランキングTOP20をSalesNowが公開、バンダイナムコや任天堂を上回った1位の企業は… GO!

サ終済みのモバイル向けRPG『BLUE REFLECTION SUN/燦』元公式サイトには接続しないで!第三者がドメイン取得し不審なWebサイトへの誘導設置 GO!
Steamでプレイテスト実施中だったゲームにマルウェア混入との告発―該当ストアページは既に閲覧できない状態に GO!
Steamストアからの成人向けゲーム削除、7月26日時点でも流れは止まらず…新たに削除されたタイトル多数 GO!

前回のコメント

・いろんな場面によって最適な方法で配列の繰り返し文を作れるようにしたいです。ジャグ配列など学べて良かったです

 是非、いろいろと試して、使い分けてください。

・ジャグ配列が難しかったです。

 次回、フォローしますので、理解を深めてください。

講義メモ 後半

p.124 無限ループを止める:補足

・プログラムが無限ループした場合、ファイルなどを保存してからUnityを終了する
 ⇒ タスクバーのUnityを右クリックし「ウィンドウを閉じる」
・終了できなければタスクバーを右クリックし「タスクマネージャ」で終わらせる
※タスクマネージャが利用できない場合:
 ・「スタート」を右クリックして「シャットダウンまたはサインアウト」で「サインアウト」
 ・サインインすると利用可能になる(ヒューマンアカデミーのPCではidは「human」と入力)
・それから、無限ループの原因となったスクリプトを修正または削除する
・なお、テキストp.125では「①歯車アイコン」とあるが「①縦の「…」アイコン」に代わっている

作成例

using UnityEngine;
public class chap3_10_1 : MonoBehaviour{
    void Start()    {
        string[] grade = {"松","竹","梅"};
        foreach(string g in grade) {
            Debug.Log(g);
        }
    }
}

p.126 復習ドリル 問題1 chap3_10_1.cs

・正誤:「ヒント:Chap3-7-2.jsにChap3-4-1.js」⇒「ヒント:chap3_7_2.csにChap3_4_1.cs」

作成例

using UnityEditor.Callbacks;
using UnityEngine;
public class chap3_10_2 : MonoBehaviour{
    void Start()    {
        string[] dirs = {"東","西","南","北","北東"};
        for (int cnt = 3; cnt >= 0; cnt--) { //逆順に繰返す
            Debug.Log(dirs[cnt] + "方向"); 
        }
    }
}

Chapter 3 補足

2次元配列について

・配列の添字を2個にしたものを2次元配列といい、縦横や年組というような表形式のデータを扱うときに便利
・配列の添字を3個以上にもできるので、まとめて多次元配列ともいう
・C#では2種類の多次元配列を扱うことができ、片方を(通常の)配列、もう片方をジャグ配列という
・なお、C/C++言語の2次元配列はC#の(通常の)配列に該当するが、表記方法が大きく異なるので注意

(通常の)2次元配列

・2つの添字を用いて「 配列名[添字①, 添字②] 」形式で扱うもの
 ※ なお、C/C++では「 配列名[添字①][添字②] 」形式になる
・1次元配列と同様に添字は0からなので、2次元配列の最初の要素は「配列名[0,0]」になる
・宣言の書式: 型[,] 配列名;
・生成の書式: 配列名 = new 型[要素数①, 要素数②];
・宣言と生成の書式: 型[,] 配列名 = new 型[要素数①, 要素数②];
・例: int[,] students = new int[3, 2]; //1~3年の1~2組の生徒数の配列
 ⇒ students[0,0] students[0,1] students[1,0] students[1,1] students[2,0] students[2,1] の6要素が生成される
・初期化の書式: 型[,] 配列名 = {{…},…}; //初期値をグループ化して与える
・例: int[,] students = {{11, 12}, {21, 22}, {31, 32}};
・なお、2次元配列名.Lengthとすることで全要素数(要素数①×要素数②)が得られる。要素数①、要素数②を動的に得ることはできない

ミニ演習 mini0720a.cs

・上記の配列studentsの全要素を添字と共に表示しよう
・forの2重ループにすると良い
・全要素数も表示しよう

作成例

//ミニ演習 mini0720a.cs
using UnityEngine;
public class mini0720a : MonoBehaviour{
    void Start() {
        int[,] students = {{11, 12}, {21, 22}, {31, 32}}; //(通常の)2次元配列
        for(int i = 0; i < 3; i++) { //2次元配列の添字①について繰返す
            for(int j = 0; j < 2; j++) { //2次元配列の添字②について繰返す
                Debug.Log("[" + i + "," + j + "] = " + students[i,j]);
            }
        }
        Debug.Log(students.Length); //6
    }
}

ジャグ配列(2次元配列の場合)

・2つの添字を用いて「 配列名[添字①][添字②] 」形式で扱うもの
・通常の配列とは異なり、配列の配列で構成する
・よって、内側の要素数が異なってもOK
 例:3学年あるが1年は2クラス、2年は3クラス、3年は2クラス
・ジャグ配列の最初の要素は「配列名[0][0]」になる
・宣言の書式: 型[][] 配列名;
・生成の書式: 配列名 = new 型[要素数①][];
・そして、1次元配列を格納する: 配列名[添字①] = new 型[要素数②];
例:
 int[][] students = new int[3][]; //3年分を確保する
 students[0] = new int[2]; //1年の2クラス分を生成
 students[1] = new int[3]; //2年の3クラス分を生成
 students[2] = new int[2]; //3年の2クラス分を生成
・初期化は内側の配列で行う
例:
 int[][] students = new int[3][]; //3年分を確保する
 students[0] = new int[]{11, 12}; //1年の2クラス分を生成
 students[1] = new int[]{21, 22, 23}; //2年の3クラス分を生成
 students[2] = new int[]{31, 32}; //3年の2クラス分を生成
・ジャグ配列名.Lengthとすることで要素数①が得られる。
 例: students.Lengthは3
・そして、ジャグ配列名[添字].Lengthとすることで、ジャグ配列を構成する配列の要素数が得られる
 例: students[0].Lengthは2、students[1].Lengthは3、students[2].Lengthは2

ミニ演習 mini0720b.cs

・上記のジャグ配列studentsの全要素を添字と共に表示しよう
・forの2重ループにすると良い
・Lengthを活用しよう

提出:ミニ演習 mini0720b.cs

講義メモ

・p.117「要素を入れずに配列を作成する」から

p.117 要素を入れずに配列を作成する

・配列の要素を要素数を指定して確保(生成)しておき、後で要素値を代入することも多い
・配列の宣言の書式: 型[] 配列名;
・配列の生成の書式: 配列名 = new 型[要素数]; //要素数の分の領域を確保(生成)する
・宣言と生成は同時に行ってよい: 型[] 配列名 = new 型[要素数]; ←p.117の書式
 例: string[] slimes = new string[3]; //要素数3の文字列型配列slimesの生成
・生成により中身の入っていない要素になるので、その要素への代入は可能だが、利用するとNull(無)が返されるので注意

アレンジ演習:p.117 Chap3_6_3.cs

・中身の入っていない要素である dirs[2]をDebug.Logするとどうなるか確認しよう
 ⇒ nullになる
・また、添字には変数や式が利用できるので、int w = 2; としておいて dirs[w]をDebug.Logするとどうなるか確認しよう
 ⇒ nullになる

作成例

//アレンジ演習:p.117 Chap3_6_3.cs
using UnityEngine;
public class chap3_6_3 : MonoBehaviour {
    void Start()    {
        string[] dirs = new string[4];
        dirs[0] = "東";
        dirs[1] = "西";
        Debug.Log(dirs[0]);
        Debug.Log(dirs[1]);
        //【以下追加】
        Debug.Log(dirs[2]); //null
        int w = 2;
        Debug.Log(dirs[w]); //null
    }
}

提出フォロー:アレンジ演習:p.116 chap3_6_2

・書き換えたい要素の添字と、書き換える文字列をパブリック変数で与えるようにしよう
・ついでに、string.Joinの区切り文字もパブリック変数で与えるようにしよう

作成例

//アレンジ演習:p.116 chap3_6_2
using UnityEditor.Callbacks;
using UnityEngine;
public class chap3_6_2 : MonoBehaviour{
    public int n; //【追加】
    public string s; //【追加】
    public string kugiri; //【追加】
    void Start()    {
        string[] dirs = {"東","西","南","北"};
        dirs[n] = s; //【変更】
        Debug.Log(string.Join(kugiri, dirs)); //【変更】
    }
}

p.118 foreach文

・第4の繰り返し構文で、配列などの複数の要素を持つデータ構造に対して「全要素について繰返す」場合に便利
・書式: foreach (型 作業変数 in 配列名など) { 作業変数を用いる処理 }
・この書式により、配列などの要素が先頭から1個ずつ作業変数に渡されて(コピーされて)繰り返し内容が
 実行される
・よって、配列をforeach文で扱うと、添字を意識する必要がなくなる
※ なお、作業変数はforeachのブロック内でのみ有効なので、ブロックを抜けた後では利用できないが、
 複数のforeachのブロックで同名の作業変数を用いても問題ない
※ ただし、作業変数を用いる処理で作業変数の値を変更することはできないので、配列の要素値を設定・変更する
 処理はできない
※ なお、作業変数の方は配列の型と一致するのが基本なので「var」キーワードを用いて省略しても良い
 (varは型を自動決定してくれる匿名型)
 ※チームルールによってはforeachではvar型と決めている場合がある

アレンジ演習:p.118 chap3_7_1

・作業変数dをforeachのブロックの外で用いると文法エラーになることを確認しよう(確認後コメントアウト)
・作業変数dにforeachのブロックの中で値を代入すると用いると文法エラーになることを確認しよう
 (確認後コメントアウト)
・作業変数dをvar型にしてみよう

作成例

//アレンジ演習:p.118 chap3_7_1
using UnityEditor.Callbacks;
using UnityEngine;
public class chap3_7_1 : MonoBehaviour{
    void Start()    {
        string[] dirs = {"東","西","南","北"};
        foreach (var d in dirs) { //【変更】var型で良い
            // d = "南東"; //【追加・削除】代入できない
            Debug.Log(d + "方向"); 
        }
        //Debug.Log(d + "方向"); //【追加・削除】ブロック外では無効
    }
}

p.119 for文を使ってインデックスを指定する

・foreach文を用いる場合に比べて冗長になるが、foreach文の制限に該当する場合は、for文で同じ処理を記述できる
・書式例:
 for(int 繰返し用の変数 = 0; 繰返し用の変数 < 要素数; 繰返し用の変数++) {…}

アレンジ演習:p.119 chap3_7_2

・繰返し用の変数cntをforのブロックの前で宣言しておけば、ブロック外で用いることができることを確認しよ
・forのブロックの中で配列の要素に値を代入できることを確認しよう

作成例

//アレンジ演習:p.119 chap3_7_2
using UnityEditor.Callbacks;
using UnityEngine;
public class chap3_7_2 : MonoBehaviour{
    void Start()    {
        string[] dirs = {"東","西","南","北"};
        int cnt; //【追加】
        for (cnt = 0; cnt < 4; cnt++) { //【変更】
            dirs[cnt] = "南東"; //【追加】代入できる
            Debug.Log(dirs[cnt] + "方向"); 
        }
        Debug.Log("添字は" + cnt); //【追加】ブロック外で有効(4になるので注意)
    }
}

補足:配列の要素数

・配列の要素数は「配列名.Length」で得られるので、要素数が必要な場合に、これを用いておけば、
 要素数を変更した場合に、自動的に追従してくれるので、保守性が向上する
 ※チームルールによっては「配列名.Length」の利用を義務と決めている場合がある
・なお「.Length」はクラスや構造体におけるプロパティと呼ばれる仕掛けの一つで、C#は配列を内部的にオブジェクトとして扱うので、
 C#が提供するプロパティがいつでも利用可能
・書式例:
 for(int 繰返し用の変数 = 0; 繰返し用の変数 < 配列名.Length; 繰返し用の変数++) {…}

アレンジ演習:p.119 chap3_7_2 つづき

・配列の要素数で「配列名.Length」を用いるように変更しよう
・すると、配列dirsに要素"北東"を加えても、処理の変更が不要なことを確認しよう

作成例

//アレンジ演習:p.119 chap3_7_2
using UnityEditor.Callbacks;
using UnityEngine;
public class chap3_7_2 : MonoBehaviour{
    void Start()    {
        string[] dirs = {"東","西","南","北","北東"}; //【変更】
        int cnt;
        for (cnt = 0; cnt < dirs.Length; cnt++) { //【変更】
            //dirs[cnt] = "南東"; 
            Debug.Log(dirs[cnt] + "方向"); 
        }
        Debug.Log("添字は" + cnt); //ブロック外で有効(自動的に5になる)
    }
}

p.120 単純に全ての組み合わせを並べる = 2重ループ

・foreach文による繰り返しの中でもさらに繰り返しが可能
・ただし、作業変数名は外側と内側で異なるものにすること
・内側のforeach文では、外側の作業変数が利用可能
・なお、3重以上の多重ループも可能

アレンジ演習:p.120 chap3_8_1

・作業変数の型を両方ともvarに変更しよう

作成例

//アレンジ演習:p.120 chap3_8_1
using UnityEngine;
public class chap3_8_1 : MonoBehaviour{
    void Start()    {
        string[] team = {"A","B","C","D" };
        foreach(var t1 in team){ //【変更】                   
            foreach(var t2 in team){ //【変更】
                Debug.Log(t1 + "vs" + t2);
            }        
        }
    }
}

p.122 単純に全ての組み合わせを並べる = つづき

・foreach文による2重ループの中で、2つの作業変数を比較する処理を記述できる

アレンジ演習:p.122 chap3_8_2

・何パターンあるか最後に表示しよう

作成例

//アレンジ演習:p.122 chap3_8_2
using UnityEngine;
public class chap3_8_2 : MonoBehaviour{
    void Start()    {
        string[] team = {"A","B","C","D" };
        int num = 0; //【追加】パターン数
        foreach(var t1 in team){                 
            foreach(var t2 in team){ 
                if (t1 != t2){
                    Debug.Log(t1 + "vs" + t2);
                    num++; //【追加】
                }
            }        
        }
        Debug.Log(num + "パターンある"); //【追加】
    }
}

p.123 同じ繰り返しを省くには

・foreachによる繰り返しとforによる繰り返しを組み合わせることで、細かい制御が可能になる

アレンジ演習:p.123 chap3_8_3

・外側のforeach文もfor文にすることで、記述をよりシンプルにしよう

作成例①

//アレンジ演習:p.122 chap3_8_3
using UnityEngine;
public class chap3_8_3 : MonoBehaviour{
    void Start()    {
        string[] team = {"A","B","C","D" };
        for(int i = 0; i < 4; i++){                 
            for(int j = 0; j < i; j++){ //内側の繰返しを外側のカウンタで制限する
                Debug.Log(team[i] + "vs" + team[j]);
            }        
        }
    }
}

作成例②

//アレンジ演習:p.122 chap3_8_3
using UnityEngine;
public class chap3_8_3 : MonoBehaviour{
    void Start()    {
        string[] team = {"A","B","C","D" };
        for(int i = 0; i < 4; i++){                 
            for(int j = i + 1; j < 4; j++){ //内側の繰返しの開始を外側のカウンタの次からにする
                Debug.Log(team[i] + "vs" + team[j]);
            }        
        }
    }
}