条件分岐と繰り返し処理の基本【Unityスタートガイド6-5】

「HPが0になったらゲームオーバー」「敵を5体出す」など、ゲームは「〜なら」と「くり返し」でできています。今回はプログラムの流れを変えるif文と、同じ処理をくり返すfor文・while文・foreach文、そしてたくさんのデータをまとめて扱う配列をご紹介します!

目次

この記事で学べること

  • if文を使った条件分岐
  • 比較演算子と論理演算子
  • for文・while文を使った繰り返し処理
  • 配列とforeach文で、たくさんのデータをまとめて扱う方法

前提知識

この記事のサンプルは、どれもStartの中に書いて再生し、Consoleで結果を見る形で試せます。6-4と同じように、空のゲームオブジェクトにスクリプトをアタッチして試してみてください。

if文で条件分岐

基本的なif文

条件を満たしたときだけ処理を実行するには、if文を使います:

int score = 70;

if (score >= 60)
{
    Debug.Log("合格です!");
}

if文の構造:

if (条件)
{
    条件がtrue(はい)のときだけ実行される処理
}

if-else文:どちらか一方

条件によって、2つのうちどちらかを実行する場合:

int score = 75;

if (score >= 80)
{
    Debug.Log("素晴らしい!");
}
else
{
    Debug.Log("もう少し頑張りましょう");
}

else if:3つ以上の分かれ道

int score = 85;

if (score >= 90)
{
    Debug.Log("Sランク!");
}
else if (score >= 80)
{
    Debug.Log("Aランク!");
}
else if (score >= 70)
{
    Debug.Log("Bランク!");
}
else
{
    Debug.Log("がんばりましょう");
}

上から順番に調べて、最初に当てはまったところだけが実行されます。85点は「90以上」には当てはまらず、「80以上」に当てはまるので「Aランク!」になります。

boolはそのまま条件に使える

6-4で紹介したbool型は、そのままifの条件に書けます:

bool isGameOver = true;

if (isGameOver)
{
    Debug.Log("ゲームオーバー");
}

比較演算子

条件の中で使う、主な比較演算子です:

演算子意味例
==等しいscore == 100
!=等しくないscore != 0
>より大きいscore > 80
<より小さいscore < 60
>=以上score >= 80
<=以下score <= 60

注意:=(代入)と==(比べる)は別物です!

論理演算子

いくつかの条件を組み合わせる場合:

int score = 85;
bool hasBonus = true;

// AND:両方ともtrueのとき
if (score >= 80 && hasBonus)
{
    Debug.Log("ボーナスポイントゲット!");
}

// OR:どちらか一方でもtrueのとき
if (score >= 90 || hasBonus)
{
    Debug.Log("特別賞!");
}

// NOT:true/falseを反対にする
if (!hasBonus)
{
    Debug.Log("ボーナスなし");
}
  • &&:AND(かつ)
  • ||:OR(または)
  • !:NOT(〜でない)

for文で決まった回数くり返す

基本的なfor文

for (int i = 0; i < 5; i++)
{
    Debug.Log("カウント: " + i);
}

実行結果:

カウント: 0
カウント: 1
カウント: 2
カウント: 3
カウント: 4

for文の構造:

for (最初に1回やること; くり返す条件; 1回ごとにやること)
{
    くり返す処理
}
  • int i = 0:カウンター用の変数iを0から始める
  • i < 5:iが5より小さい間くり返す
  • i++:1回終わるごとにiを1増やす(i = i + 1と同じ)

0から数えて「5より小さい間」なので、0〜4の5回実行されます。

while文で条件を満たす間くり返す

基本的なwhile文

int hp = 30;
int damage = 8;
int turn = 0;

while (hp > 0)
{
    hp -= damage;
    turn++;
    Debug.Log(turn + "ターン目:残りHP " + hp);
}

Debug.Log(turn + "ターンで倒した!");

実行結果:

1ターン目:残りHP 22
2ターン目:残りHP 14
3ターン目:残りHP 6
4ターン目:残りHP -2
4ターンで倒した!

何回くり返すか最初からは分からないけど、「HPが0より大きい間」のように条件で止めたいときはwhile文を使います。

注意:条件がずっとtrueのままだと、無限ループになってUnityが固まります!

// 危険:hpを減らし忘れていて、永遠に終わらない
while (hp > 0)
{
    Debug.Log("止まらない!");
}

5-1の記事で説明したとおり、固まったUnityは強制終了するしかありません。whileを書くときは、くり返しの中で条件が変わるかを必ず確認しましょう(再生前のCtrl+Sもお忘れなく)。

配列とforeach文:たくさんのデータをまとめて扱う

配列とは

同じ型のデータを、番号付きでまとめて入れておく箱です。

string[] enemyNames = { "スライム", "ゴブリン", "ドラゴン" };

Debug.Log(enemyNames[0]);        // スライム(番号は0から始まる)
Debug.Log(enemyNames[2]);        // ドラゴン
Debug.Log(enemyNames.Length);    // 3(入っている数)
  • 型[]で配列になる
  • 番号(インデックス)は0から始まる。3つ入っている配列の最後は[2]
  • 存在しない番号([3]など)を使うと、5-3の記事で紹介したIndexOutOfRangeExceptionになります

Inspectorで配列を設定する

[SerializeField]を付けると、配列もInspectorで中身を設定できます:

[SerializeField] private int[] stageScores = { 100, 250, 400 };

Inspectorに「Stage Scores」の欄が出て、+ボタンで数を増やしたり、値を書き換えたりできます。

foreach文で全部を順番に取り出す

string[] enemyNames = { "スライム", "ゴブリン", "ドラゴン" };

foreach (string enemyName in enemyNames)
{
    Debug.Log(enemyName + "があらわれた!");
}

配列の中身を、最初から最後まで1つずつ取り出してくり返します。番号を気にしなくていいので、「全部に同じことをする」ときはforeachが便利です。

実践サンプル:ステージの結果を判定する

今までの内容を組み合わせてみましょう。Inspectorでステージごとのスコアを設定しておき、合計と評価をConsoleに表示します。

using UnityEngine;

public class StageResult : MonoBehaviour
{
    [SerializeField] private int[] stageScores = { 80, 95, 60 };
    [SerializeField] private int clearLine = 70;

    void Start()
    {
        int total = 0;
        int clearCount = 0;

        // 全ステージのスコアを順番に調べる
        for (int i = 0; i < stageScores.Length; i++)
        {
            int score = stageScores[i];
            total += score;

            if (score >= clearLine)
            {
                clearCount++;
                Debug.Log("ステージ" + (i + 1) + ":" + score + "点 クリア!");
            }
            else
            {
                Debug.Log("ステージ" + (i + 1) + ":" + score + "点 もう一息");
            }
        }

        // 最後に全体の評価
        if (clearCount == stageScores.Length)
        {
            Debug.Log("全ステージクリア!合計 " + total + "点");
        }
        else
        {
            Debug.Log(clearCount + "ステージクリア。合計 " + total + "点");
        }
    }
}

このサンプルのポイント:

  • 配列:ステージのスコアをまとめてInspectorで設定出来る
  • for文:何番目のステージかを表示したいので、番号付きでくり返す
  • if-else:クリアラインを超えたかどうかでメッセージを変える
  • InspectorでStage ScoresやClear Lineの値を変えて再生し直すと、結果が変わります

注意点やヒント

インデント(字下げ)をそろえましょう

{ }の中は1段下げて書くと、どこからどこまでがifの中なのかが一目で分かります。VS CodeでShift+Alt+F(Macの場合はShift+Option+F)を押すと、自動で整えてくれます。

長い条件は変数に分ける

// 読みにくい例
if (score >= 90 && hp > 0 && !isGameOver)
{
    Debug.Log("ハイスコアで生き残った!");
}

// 読みやすい例:条件に名前を付ける
bool isHighScore = score >= 90;
bool isAlive = hp > 0 && !isGameOver;

if (isHighScore && isAlive)
{
    Debug.Log("ハイスコアで生き残った!");
}
スライム

if文の中にif文を書いて、さらにその中に・・・と深くなりすぎて迷子になった・・・

フェアリー

入れ子は2段ぐらいまでを目安にしよう!深くなってきたら、次の6-6で覚える「メソッド」に分けるとスッキリするよ

よくあるエラーと対処法

エラー:無限ループでUnityが固まった

  • 原因:while文の条件が、ずっとtrueのまま変わらない
  • 対処法:Unityを強制終了して、くり返しの中で条件の変数を更新しているか確認する

エラー:ifの条件が思った通りに動かない

  • 原因:=(代入)と==(比較)を間違えている。またはelse ifの順番が違う(上から順に調べるので、>= 70を>= 90より先に書くと、90点でもBランクになる)
  • 対処法:比較は==。範囲のチェックは、厳しい条件から順に書く

エラー:IndexOutOfRangeException

  • 原因:配列の存在しない番号を使った(例:3つの配列で[3])
  • 対処法:番号は0から始まることを思い出す。forの条件はi < 配列.Lengthにする

エラー:論理演算子の組み合わせで結果がおかしい

  • 原因:&&と||を混ぜたときの順番
  • 対処法:迷ったらカッコでくくる:if ((a && b) || c)

まとめ

  • if文:条件によって処理を分ける(else if は上から順に調べる)
  • 比較演算子:==, !=, <, >, <=, >=
  • 論理演算子:&&(AND), ||(OR), !(NOT)
  • for文:決まった回数くり返す
  • while文:条件を満たす間くり返す(無限ループに注意)
  • 配列とforeach:たくさんのデータをまとめて扱う

次のステップ

処理が長くなってきたら、まとまりごとに名前を付けて分けましょう。次は自分で「メソッド」を作る方法です:

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

コメント

コメントする

目次