前回のコメント

・ゲームを作る際にif文はかなり頻出だと思うので混乱しないように過不足ない条件がかけるようにしたいです。

 応援します。

・文字は文字コードで比較するのが面白いと思いました。

 特に、数値と数字の違いが誤解しやすいですね。しっかり理解してください。

講義メモ 後半

p.076 if文

・条件に応じて実行内容を変更できるのが分岐構文で、最も代表的な分岐構文がif文。
・書式例: if(bool型の式){式がtrueの場合に実行する文; …}
・bool型の式として、比較演算子の式を用いると「●が■なら▲する」という構文を記述しやすい
・例: if (a > 0) { Debug.Log("aは正の数"); }
・ifの{}をブロック(ifブロック)といい、通常、内容をインデントして対象範囲をわかりやすくする(VSでは自動的に行われる)
・テキストでは「Tabキーを押して」とあるが、複数個のスペースでも良く、チームルールが決められていることもある。

アレンジ演習:p.077 Chap2_4_1

・「●歳は未成年」というように、ageの値も表示しよう

作成例

using UnityEngine;
public class Chap2_4_1 : MonoBehaviour {
    public int age;
    void Start() {
        if (age < 20) { //ageの値が20未満?
            Debug.Log(age + "歳は未成年"); //表示
        } //ageの値が20以上ならばなにも表示しない
    }
}

p.078 ブロック内で複数の処理を行う

・ブロック内で複数の処理を行うことができる
・なお、ブロック内が1文であれば{}を省略できるが、推奨されない場合もある
 ※if文の対象範囲がわかりづらくなり、保守性が下がる懸念があるため

アレンジ演習:p.077 Chap2_4_1⇒Chap2_4_2

・未成年であれば、成年まであと何年かも表示しよう
・例:
「19歳は」
「未成年」
「成年まであと1年」

作成例

using UnityEngine;
public class Chap2_4_1 : MonoBehaviour {
    public int age;
    void Start() {
        if (age < 20) { //ageの値が20未満?
            Debug.Log(age + "歳は"); //表示
            Debug.Log("未成年"); //表示
            Debug.Log("成年まであと" + (20 - age) + "年"); //【追加】
        } //ageの値が20以上ならばなにも表示しない
    }
}

p.079 ブロックとフローチャート:分岐からの合流

・分岐構造のポイントは入口も出口も1つずつであり、どう分岐しても必要な処理を終えたら合流する
 ※まれに合流せずに終了する場合もあるが、本来の形ではない

アレンジ演習:p.077 Chap2_4_1⇒Chap2_4_2 つづき

・p.079の通りブロックの外で「ブロック外だよ」を表示しよう
・すると、未成年の場合もそうではない場合も「ブロック外だよ」が表示されることを確認しよう

作成例

using UnityEngine;
public class Chap2_4_1 : MonoBehaviour {
    public int age;
    void Start() {
        if (age < 20) { //ageの値が20未満?
            Debug.Log(age + "歳は"); //表示
            Debug.Log("未成年"); //表示
            Debug.Log("成年まであと" + (20 - age) + "年");
        }
        Debug.Log("ブロック外だよ"); //常に表示される //【追加】
    }
}

p.080 else文

・1つのifには1つだけelseとそのブロックを追記して「●が■なら▲する、でなければ▼する」という構文を記述できる
・elseも対象が1文のみであれば{}を省略できるが、推奨されないことがある。
 ※ ifの{}があるときに、elseの{}を省略するのは避けた方が良い。
・対応するifがないelseは文法エラーになる

アレンジ演習:p.081 Chap2_5_1

・未成年であれば「成年まであと何年」を表示しよう
・成年であれば、「成年からもう何年」も表示しよう

作成例

using UnityEngine;
public class Chap2_5_1 : MonoBehaviour {
    public int age;
    void Start() {
        if (age < 20) { //ageの値が20未満?
            Debug.Log("未成年"); //表示
            Debug.Log("成年まであと" + (20 - age) + "年");
        } else {
            Debug.Log("成人"); //表示
            Debug.Log("成年からもう" + (age - 20) + "年");
        }
    }
}

p.84 else-if文

・if文にelse-ifを書き加えることで「●が■なら▲する、ではなく▼ならば★する」という構文を記述できる
 例:if(a < 20) { Debug.Log("未成年"); } 
   else if(a > 60)  { Debug.Log("高齢者"); }
・else-ifは複数記述できる
・最後のelse-ifの後に1つだけelseブロックが記述できる
・これにより「上記のどれにも当てはまらない場合は☆する」という構文が可能

アレンジ演習:p.081 Chap2_6_1

・未成年であれば「成年まであと何年」を表示しよう
・成年であれば、「成年からもう何年」も表示しよう
・高齢者であれば、上記は表示しなくて良い

作成例

using UnityEngine;
public class Chap2_6_1 : MonoBehaviour {
    public int age;
    void Start() {
        if (age < 20) { //ageの値が20未満?
            Debug.Log("未成年"); //表示
            Debug.Log("成年まであと" + (20 - age) + "年");
        } else if (age < 65) { //ではなくて(20以上で)65未満?
            Debug.Log("成人"); //表示
            Debug.Log("成年からもう" + (age - 20) + "年");
        } else { //上記のどれもなければ(65以上?)
            Debug.Log("高齢者"); //表示
        }
    }
}

p.84 else-if文:補足

・同じ変数を比較に用いる場合などで、else-if構造にすると、分岐の順序によって実行されない部分ができてしまうことに注意を。
・例えば、Chap2_6_1で「age < 20」と「age < 65」を逆にすると「未成年」が表示されなくなる
・VSでは可能な限り、このような問題点を指摘してくれるが、されないこともある

アレンジ演習:p.081 Chap2_6_1:つづき

・ifの条件とelse-ifの条件、それぞれの実行内容を取り換えるとどうなるか確認しよう
 ⇒文法エラー等にはならず警告も表示されないが、絶対に実行されない部分ができてしまう

作成例

using UnityEngine;
public class Chap2_6_1 : MonoBehaviour {
    public int age;
    void Start() {
        if (age < 65) { //ageの値が20未満?
            Debug.Log("成人"); //表示
            Debug.Log("成年からもう" + (age - 20) + "年");
        } else if (age < 20) { //ではなくて(20以上で)65未満? ←無意味
            Debug.Log("未成年"); //表示 ←ageがどんな値でも実行されない
            Debug.Log("成年まであと" + (20 - age) + "年"); //←同上
        } else { //上記のどれもなければ(65以上?)
            Debug.Log("高齢者"); //表示
        }
    }
}

提出:アレンジ演習:p.081 Chap2_6_1:つづき②

・上記の変更を元に戻してから、ageが負の数であれば「負の数は用いない」と表示する処理を追加しよう

講義メモ

・p.070「Chapter 2のためのゲームオブジェクトの追加」から

p.070 空のゲームオブジェクトを追加する

・「create」をクリック ⇒ 左上の「+」をクリック

p.072 比較演算子

・p.69の例に登場した「age < 20」の「<」は2項<演算子といい、左辺が所定の比較方法により右辺より小さいとなる場合にtrueを、
 でなければfalseを返すもので比較演算子(関係演算子)の一つ
・比較演算子(関係演算子)は2項<(小なり),>(大なり),<=(以下),>=(以上),==(等価),!=(非等価)演算子の6種。
・「<=」「>=」「!=」は「=」が右側。「==」を含めて間の空白は不可
・比較演算子が返すbool値(true/false)をDebug.LogするとTrue/Falseとなる。

アレンジ演習:p.073 Chap2_3_1.cs

・Chap2_3_2.csも含めよう
・2項<=(以下),>=(以上),==(等価),!=(非等価)演算子も試そう(エラーも)
 ⇒「< =」とすると「=は無効です」エラーになる
 ⇒「=>」とすると「構文エラーです。','が必要です」になる
 ⇒「=!」とすると左辺・右辺の値により異なるエラーになるので注意

作成例

using UnityEngine;

public class chap2_3_1 : MonoBehaviour {
    void Start() {
        Debug.Log(4 < 5); //True        
        Debug.Log(6 < 5); //False        
        Debug.Log(4 <= 5); //True        
        Debug.Log(4 >= 5); //False        
        Debug.Log(4 == 5); //False        
        Debug.Log(6 != 5); //True        
    }
}

補足:整数と実数の比較演算子による処理

・整数と実数を比較演算子のオペランドにした場合、実数に揃えた結果で比較される
・例えば、整数5と実数5.0は厳密には等しくないが、整数5を実数5.0にしてから比較するので等価になる
・整数型、実数型などで型が異なる変数の場合も基本的に同様

アレンジ演習:p.073 Chap2_3_1.cs:つづき

・各種の整数型、実数型、文字型、論理型の変数を交えて、比較可能か確認しよう
 ⇒整数型、実数型、文字型の混在による比較は可能(型を揃えてから行われる)。
  ただし、文字型と整数型・実数型の比較は文字コードによって行われる
  よって、文字'4'と整数4は等しくない。
  論理型と、論理型以外の型の混在による比較は文法エラーになる。

作成例

using UnityEngine;

public class chap2_3_1 : MonoBehaviour {
    void Start() {
        Debug.Log(4 < 5); //True        
        Debug.Log(6 < 5); //False        
        Debug.Log(4 <= 5); //True        
        Debug.Log(4 >= 5); //False        
        Debug.Log(4 == 5); //False        
        Debug.Log(6 != 5); //True        
        int i = 5; uint u = 5U; float f = 5.0f; double d = 5.0; char c = '5';
        Debug.Log("5 == 5U : " + (i == u)); //True(longで比較)
        Debug.Log("5 == 5.0F : " + (i == f)); //True(floatで比較)
        Debug.Log("5 == 5.0 : " + (i == d)); //True(doubleで比較)
        Debug.Log("5 == '5' : " + (i == c)); //False(文字コードをintで比較)
        Debug.Log("65 == 'A' : " + (65 == 'A')); //True(同上,'A'はコード65)
        bool b = false;
        //Debug.Log("5 == false : " + (i == b)); //文法エラー
        //Debug.Log("'5'== false : " + (c == b)); //文法エラー
    }
}

p.074 パブリック変数を組み合わせてみよう

・変数値をパブリック変数で与えることで、比較結果が変わることを確認できる

アレンジ演習:p.074 Chap2_3_3.cs

・実数値や文字もパブリック変数で与えて、これらを用いる比較演算を行い、動作を確認しよう

作成例

//アレンジ演習:p.074 Chap2_3_3.cs
using UnityEngine;
public class chap2_3_3 : MonoBehaviour {
    public int age;
    public double aged;
    public char agec;
    void Start() {
        Debug.Log(age < 20); //整数比較
        Debug.Log(aged < 20); //20.0にして実数比較
        Debug.Log(agec < 20); //文字コードで比較
    }
}

p.075 文字列を比較する

・文字列どうしの等価比較(==、!=)は文字列として全く同じかどうかの比較になる
・大文字小文字、1バイト文字2バイト文字は別の文字として扱われる

p.075 mini075.cs 文字列を比較する

・文字列どうしの大小比較がどうなるか試そう ⇒文法エラーになる
・文字列型と他の型との比較演算ができるかどうか試そう ⇒文法エラーになる

作成例

using UnityEngine;
public class mini075 : MonoBehaviour {
    void Start() {
        Debug.Log("apple" == "apple"); //True
        Debug.Log("apple" == "orange"); //False
        Debug.Log("apple" != "apple"); //False
        Debug.Log("apple" != "orange"); //True
        //Debug.Log("apple" < "orange"); //文法エラーになる
        //Debug.Log("apple" == 0); //文法エラーになる
        //Debug.Log("apple" == 'a'); //文法エラーになる
    }
}

補足: 比較の左辺と右辺の使い分けについて

・変数とリテラルを比較する場合「変数 演算子 リテラル」でも「リテラル 演算子 変数」でも問題ない
・しかし、チームルールによっては「変数 演算子 リテラル」とすることを推奨している場合がある
 例:「6 < a」は「a > 6」にする
・なお、複数の比較演算子の連続記述はエラーになる
 例:「6 < a < 10」//文法エラー
・ちなみに「6 == a == true」であれば先に「6 == a」が評価されてbool値が返るのでエラーにならない

今週の話題

ゲームソフト販売本数ランキング:今週1位は「マリオカート ワールド(Switch2)」 GO!
Switch2の“Cボタン”使ってみたらスゴかった。ノイズ除去や通話の文字起こしが可能、カメラの設定も簡単。『マリオカート ワールド』はおしゃべりしながらフリーランすると楽しい! GO!
ゲームクリエイターなら勉強しておきたい!業界で長年戦ってきたライターが紹介する、役立つ資格10選 GO!
バンダイナムコ、ファンドを通じてVTuber企業Million Productionに投資…Z世代以下に人気のタレントのゲーム展開も視野 GO!

鳴り物入りの宣伝に厳しい評価の『MindsEye』、PS Storeでも返金報告。今後どこまで拡大するか GO!
「盗作の底なし沼」ディズニー、画像生成AIのミッドジャーニーを著作権侵害で訴える。学習段階の侵害や幇助も主張 GO!

前回のコメント

・内部クラスでインスタンスを作成した方が安全かつスクリプトが増えず便利なんだなと勉強になりました。

 そうですね。
 他のプログラムと共有するクラスであれば、独立したクラスにすべきですが、
 用途が限られている場合、内部クラスの方が安全で、管理しやすくなります。

講義メモ 後半

p.062 エラーメッセージを読み解こう:名前を間違えた場合

・テキストでは英語表記になっているが、Unity6でVS2022を用いている場合、該当する位置に赤い波線が表示され、
 マウスを載せると日本語で説明が出る。
 例:「CS0103 現在のコンテキストに '●' という名前は存在しません」
 ※バージョンやエラーの種別によっては表示されない場合がある
・これを無視してVS2022で保存すると、Unity側に英文でエラーが表示される
 ⇒これが、p.63のエラーメッセージ
・エラーメッセージには行番号が含まれているので、長いコードになったら確認に用いると良い
・「CS0103」はエラーコードで、C#リファレンスで詳細を調べることができる
 https://learn.microsoft.com/ja-jp/dotnet/csharp/language-reference/compiler-messages/cs0103
・なお、Unityが提供する静的メソッドの名前を間違った場合は、エラーコードCS0117になる。

Chapter 2 条件によって分かれる文

p.068 条件分岐

・プログラムは順次構造と分岐が構造の基本になっており、分岐を上向きにすることで繰り返し構造を表現できる
・Chapter 1 のプログラムは全て順次構造のみで記述されている
・分岐の構造は必ず合流することがポイントで、終了させるような分岐も、内部的はプログラム終了の直前に合流し、実行後の後始末が行われる。
・フローチャートはアルゴリズムを図示する手法の国際標準で、言語などに依存せずに手順を表現・記録するための仕掛け。
・フローチャートの記述には「https://www.drawio.com/」が便利
・なお、p.068のフローチャートには開始と終了が省略されており、正しいフローチャートでは長円形で先頭と末尾に示すと良い
・また、条件を示す菱形からは→で飛び先を示し、その上にYes/True、No/Falseなどを記入する

p.069 TrueとFalse

・p.056のbool型で説明した通り、C#では真理値である真をtrue、偽をfalseとして表すことができる
・分岐の構造の条件判断も基本的に二択であり「あてはまる」をtrue「あてはまらない」をfalseで表す
・よって条件「age < 20(変数ageの値が20未満)」はageの値が18ならtrueになり、25ならfalseになる
・この「<」は演算子の一つで、比較演算子に含まれる(p.072で後述)
・なお、bool型を返すメソッドもあり、条件として用いることが可能
 例:Mathf.IsPowerOfTwo(値) //値が2のべき乗ならtrueを、でなければfalseを返す
・ちなみに、p.068のフローチャートではfalseの場合はなにもせずに合流することを表している

提出:ミニ演習 mini061.cs・改造

講義メモ

・p.060「メソッドの.(ドット)の前にあるものは」から

p.060 メソッドの.(ドット)の前にあるものは

・C言語やC++などの関数とC#やJavaなどのメソッドは近い概念だが、メソッドの基本は「クラスや構造体に所属する」ことが異なる
・よって例えば「Debug.Log」メソッドは、DebugクラスのLogメソッドを示す
・つまり「.」は日本語の「の」
・なお、自前のクラス内に自前のメソッドを書くと、自前のクラスに所属するメソッドとして扱われるが、
 自分の中なので「自前のクラス名.」は基本的に不要。
・Unityでは機能ごとにクラスを提供し、その中にメソッドを置くことで、グループ化すると共に「同じ名前でもクラスが違うと別のもの」に
 なっている

p.061 静的メソッドとインスタンスメソッド

・自らのデータを持つ必要がないメソッドと、必要があるメソッドがある
・例えば、Debug.Logは引数で与えられた情報を処理するだけなので、自らのデータを持つ必要がない
・このようなメソッドはクラスに所属するだけで良いので、静的メソッドとなりキーワード「static」を付けて定義される
・MathfクラスのMathf.MaxやMathf.Sqrtも同様
・これに対して、スライムをクラスで扱う場合、HPやMPはクラスではなくクラスをもとに生成するオブジェクト(インスタンス)で
 持つ必要がある
・例えばスライムのスラリンを表現するには、スライムはクラス(設計図)、スラリンはインスタンス(実体)とすることで、
 他のスライムの個体も扱える
・ということは、スライムクラスにHPやMPを扱うメソッドを記述した場合、これはクラスではなくインスタンスに含まれないと困る
・このようなメソッドがインスタンスメソッドで、これが本来のメソッド。
例:
class Slime { 
  public int hp = 10; 
  public void dispHP() { Debug.Log(hp); } //クラス定義
}
:
Slime sulalin = new Slime(); //スライムクラスのインスタンスsulalinを生成
sulalin.dispHP(); //インスタンスメソッドでsulalinのHPを表示(10)
sulalin.hp = 20;  //sulalinのHPを変更
sulalin.dispHP(); //インスタンスメソッドでsulalinのHPを表示(20)
Slime hoimin = new Slime(); //スライムクラスのインスタンスhoiminを生成
hoimin.hp = 50;  //hoiminのHPを変更
hoimin.dispHP(); //インスタンスメソッドでhoiminのHPを表示(50)

・p.061には書かれていないが、クラスにはデータ(インスタンス変数)を定義でき、生成したインスタンスごとに領域がとられ、
 これを扱うにはインスタンスメソッドを用いる

ミニ演習 mini061.cs

・スライムクラスを実装してインスタンスメソッドを試してみよう
・Unityの場合、制限があり、用意されるクラスの中にクラスを定義して用いる(内部クラスという)

作成例

using UnityEngine;

public class mini061 : MonoBehaviour {
    class Slime { //スライムを表すクラス(内部クラス)
        public int hp; //インスタンス変数(インスタンスごとの変数)
        public void dispHP() { //インスタンスメソッド
            Debug.Log("HPは" + hp); //インスタンス変数の値を用いる
        }
    }
    void Start() {
        Slime slalin = new Slime(); //スライムクラスのインスタンスslalinを生成
        slalin.hp = 20; //インスタンスslalinのHPを設定
        slalin.dispHP(); //slalinのインスタンスメソッドdispHPを呼ぶ 
        Slime hoimin = new Slime(); //スライムクラスのインスタンスhoiminを生成
        hoimin.hp = 50; //インスタンスhoiminのHPを設定
        hoimin.dispHP(); //hoiminのインスタンスメソッドdispHPを呼ぶ 
    }
}

補足:静的メソッドとインスタンスメソッドの共存(使い分け)

・クラスに含まれる情報には、インスタンスごとに持つべきデータ(インスタンス変数)と、
 クラスで持った方が良いデータ(静的変数(クラス変数))がある
・インスタンス変数の例:HP、MP、名前など
・静的変数(クラス変数)の例:種族名、生成したインスタンスの数など
・よって、インスタンス変数を扱うメソッドはインスタンスメソッドにする
・静的変数(クラス変数)を扱うメソッドは静的メソッドにする
・静的変数(クラス変数)の書式例: public static 型 変数名;
・静的メソッドの書式例: public 戻り値型 メソッド名(引数型 引数名,…) {…}
・静的メソッドとインスタンスメソッドの共存できるが、静的メソッドからはインスタンス変数やインスタンスメソッドは使えない
 (特定できないので)

ミニ演習 mini061.cs・改造

・静的変数(クラス変数)として下記を追加
 public static string cname = "スライム";
・静的メソッドとして下記を追加
 public void dispCname() { Debug.Log("種族:" + cname); }
・インスタンス変数として下記を追加
 public string name;
・dispHP()メソッドでnameも表示するようにしよう
・start()において、slalin.name、hoimin.nameに名前を代入しよう
・静的メソッドであるdispCname()は「Slime.dispCname()」で実行しよう

作成例

using UnityEngine;

public class mini061 : MonoBehaviour {
    class Slime { //スライムを表すクラス(内部クラス)
        public static string cname = "スライム"; //静的変数(クラスごとの種族名)
        public static void dispCname() { //静的メソッド
            Debug.Log("種族:" + cname); //静的変数の値を用いる
        }
        public string name; //インスタンス変数(インスタンスごとの名前)
        public int hp; //インスタンス変数(インスタンスごとのHP)
        public void dispHP() { //インスタンスメソッド
            Debug.Log(name + "のHPは" + hp); //インスタンス変数の値を用いる
        }
    }
    void Start() {
        Slime.dispCname(); //静的メソッドで種族名を表示(インスタンス不要)
        Slime slalin = new Slime(); //スライムクラスのインスタンスslalinを生成
        slalin.name = "スラリン"; //インスタンスslalinのnameを設定
        slalin.hp = 20; //インスタンスslalinのHPを設定
        slalin.dispHP(); //slalinのインスタンスメソッドdispHPを呼ぶ 
        Slime hoimin = new Slime(); //スライムクラスのインスタンスhoiminを生成
        hoimin.name = "ホイミン"; //インスタンスhoiminのnameを設定
        hoimin.hp = 50; //インスタンスhoiminのHPを設定
        hoimin.dispHP(); //hoiminのインスタンスメソッドdispHPを呼ぶ 
    }
}

今週の話題

ゲームソフト販売本数ランキング:今週1位は「ELDEN RING NIGHTREIGN(PS5)」 GO!
“SUMMER GAME FEST 2025”発表まとめ。『バイオ9』『コードヴェイン2』発表、龍が如くチーム新作の最新情報も! GO!
6月5日配信「State of Play」ピーク時視聴者数が最高記録達成!225万人超え GO!
「Nintendo Live 2025」開催決定。スイッチ2ゲーム体験や『マリオカート ワールド』で世界各地のプレイヤーが競うイベント実施 GO!
「スイッチ2」での「スイッチ」ソフト動作確認状況が一目瞭然!マイニンテンドーストアにて互換性表記開始 GO!

『ボーダーランズ2』レビュー荒らしのきっかけとなった利用規約変更について声明公開―スパイウェアは使用しておらず、シングルプレイ&非商用Modは黙認の方針 GO!
「Ubisoft Forward」2025年は開催されない見通し?海外ジャーナリスト報じる。5月には一部主要タイトル延期発表も GO!