前回は条件分岐についてやりました。今回もちょっとプログラムらしいことをやってみたいと思います。ループ処理というのができるようになるとできる事がたくさん増えるので覚えましょう。
↑の動画でも解説しています。文章を見るよりわかりやすいと思うので是非ご活用ください
この記事は本のように順を追って解説しています。この記事は途中のページになります。
この記事を見ていて、現在の状況がわからない場合や忘れてしまった事などが出てきたら↓のリンクから目次ページへ飛べますので立ち戻って見てください。
<ループ文とは>
さて、今回は繰り返しの処理、ループ文について解説していきたいと思います。
同じ処理を何回も行いたい時、何個も同じ文をコピペして貼り付けているとプログラムがぐちゃぐちゃになって読みづらくなってしまいます。
また、コピペで貼り付けて同じ処理を量産していると、その内容を変更したくなった場合、全部書き換えを行う事になって大変です。
これらの問題をループ文を書く事でスッキリ短く書く事ができます。
ループ文というのは書いて字のごとく何回もループして同じ処理を繰り返すものになります。
処理を繰り返すっていうとただ単調に終わりまでずっとひたすら同じ事をやっているように感じるかもしれませんが、実は様々な使い方があります。
「全部の中から当てはまるものを探す」みたいな検索機能や「全体に効果を適用する」みたいな拡散機能みたいなものだったり、色々な使い道があるので覚えておくと便利です。
と、いう事でループ文を解説していきたいのですが、ループ文にはいくつか種類があるので1つ1つ解説していきたいと思います。
<whileループ>
ループ文の中で基本的な物にwhileループというものがあります。
あまり深く考えずにとりあえずやってみましょうか
↑のように書いてみてください。実行すると
と、こういう感じでDebug.Logを1回しか書いてないのに5回表示されている事がわかります。
今は5回なので利便性があまり感じられませんが、何百、何千回とか、あと何回するか不明な時などにも便利です。
書き方としては
while ( bool型 )
{
ループの中身
}
という感じです。
bool型がtrueの時ループし続けるという文になります。
逆にいうとループをやめたければ条件式のbool型がfalseになればループをやめられます。
↑の場合aが5になるとa < 5はfalseになるのでループが終わります。なのでログには4までが表示されたわけですね。
ここで注意です。このbool型が一生trueだった場合、無限ループという現象に陥ってUnityがフリーズします。
こうなったらしょうがないので強制終了しましょう。
例えば
int a = 0;
bool b = a < 5;
while(b)
{
++a;
}
とした場合、一見↑と同じに見えますが、無限ループに陥ってフリーズします。
bにはすでにtrueが代入されており、whileループの間この値が変わらないのでフリーズします。
これを直すには
int a = 0;
bool b = a < 5;
while(b)
{
++a;
b = a < 5;
}
と、また代入し直してあげることによって普通に動くようになります。
このようにwhileループを使用する際は無限ループに陥らないように注意しましょう。
<Updateとループ文との違い>
以前Updateというのをやりましたが、Updateもループ文なんじゃないの?って疑問が出てくるかもしれませんが、実は全然違います。
Updateは毎フレームUnity側から呼ばれているだけです。
ループ文というのは1フレーム内で全て処理します。
とりあえずよくわからないと思うのでやってみましょう。
↑のような処理で書いてみましょうか。
このtransform.positionを使うやり方は以前紹介したものと一緒です。
transform.position += Vector3.right; この命令を書く事で
このスクリプトをCubeにくっつけると、再生時にCubeが右側に移動していました。
もし、ループ文とUpdateが同じようなものだったら、再生すると以前やったみたいにCubeが右側に移動していきそうです。
イメージとしては↓のような感じで動きそうな気がします。
ところが、実際再生すると一瞬で5の位置に移動します。
右へ移動するというより瞬間移動です。
ログを見てみると
確かに1ずつ移動しているのがわかります。ですが、移動経過途中は見えずに一瞬で移動してしまいました。
これは、ループ文に書かれた処理が1フレーム内で実行されるからです。(基本的には)
フレームがよくわからない方は↓の記事を参照してみてください。
さて、このフレームでの処理ですが、Updateは毎フレーム呼び出されるものでした。
つまりUpdateは
(計算処理の中で呼ばれる→描画)→(計算処理で呼ばれる→描画)→・・・以下ループ。
という感じで計算結果を反映させて描画を繰り返しています。
(計算処理の中で呼ばれる→描画)←コレが1フレームになります。
そのため、Cubeが動いたものが描画、Cubeが動いたものが描画・・・と繰り返されます。
これが高速で行われる事でパラパラ漫画のようになり、動いて見えます。
今度はループ文の場合、
(計算処理で呼ばれる(ここでループ)→描画)
で終わりです。
このように1フレーム内で全てのループが完了してしまいます。
このため、描画される前に全てのループを終えてから描画したので一瞬で移動したわけですね。
以上のことよりUpdateとループ文は全然違う事がわかります。
<breakとcontinue>
ループ処理は途中で制御することもできます。
↑のような感じで書いてみてください。
ちょっと恐ろしい書き方をしています。while(true)になっているので絶対に無限ループに突入してしまいそうです。
ですが、実行するとコンソールウィンドウにいきなり10と表示されて終わると思います。なぜでしょうか?
感のいい人はもう分かったと思いますが、continueとbreakですね。
continueというのは、これが呼ばれるとここより下の文は実行せずにループ処理に戻ります。
↑の例で言うと、もしaが10より下の時、continueと書いてあります。
aが10より下の時、continueから下の部分が実行されません。
aが10より下の間は++aしか実行されていないということになります。
そのため、1〜9は表示されず、コンソールウィンドウにいきなり10と表示されます。
breakは、これが呼ばれるとループ文を抜けます。
while(true)は無限ループを表しますが、breakにより途中で抜けているので無限ループにならずに済んでいるわけです。
無限ループに陥ってしまうとフリーズしてしまうのでbreakはとても重宝します。
<do〜while文>
さて、while文で
int a = 0;
while(a > 5)
{
++a;
Debug.Log(a);
}
という風に、「a < 5」を反対にして「a > 5」とした場合どうなるでしょうか。
これで実行しても何も起きないと思います。
それはまぁ、そうで、「a > 5」がfalseなので何も実行されずに終わったわけです。
{ }の中に入る前に条件判定があって、条件を満たした時{ }の中に入る感じですね。
do〜while文というのはこれを反対にした文です。
↑のように書いてみてください。今度はコンソールウィンドウに1だけ表示されると思います。
「a > 5」はfalseなのでこれはループしないのですが、do〜while文は条件判定を後で行う文です。
そのため、条件に関係なくとりあえず一回やってみて、その後ループするかどうか決める感じになります。
do〜while文はこの条件判定が後か先かという部分でしかwhile文と変わりません。
while文とどっちを使うのかは状況やお好みといった感じでしょうか
<for文>
forループ
while文、do〜while文は無限ループに陥ってしまうという恐ろしさがありました。ちょっと条件を書き間違えるとフリーズしてしまいます。
フリーズしてUnityを落としてしまった場合、それまでのセーブしてなかったデータがぱーになったりします。
そこでfor文というのを使うと便利なのでやってみましょう。
↑のように書きます。
なんか++iでなくi++と書くのがお行儀がいいらしいですが、どっちでも結果は一緒です。
for文はまずループさせるための変数を定義します。
int i = 0というのがそうですね。
whileで使っていたaとおんなじです。
なんか一般的にiと書かれる事が多い(intの略)からこう書いてますが、別にint a = 0と書いてもいいです。
次にループさせるための条件を書きます。 i < 5 の部分ですね。これがtrueの間ループします。
最後にループする前にやる事を書きます。++i の部分ですね。
for(定義 ; 条件 ; ループ時にやる事)
{
}
みたいな感じです。
↑の文をwhile文で書くとこうなります。
int i = 0;
while ( i < 5 )
{
Debug.Log(i);
++i;
}
こう書くのと意味は同じです。
whileもforも同じループ文なので書き方や使い方が違うだけで大筋の処理はほとんど一緒です。
こんなにごちゃごちゃ書くより1行でスッとかけるのでループ条件が簡単なら基本的にfor文を使った方がいいかなと思います。
何を使うかはお好みですが、無限ループに入りづらいのでこちらの方がオススメですかね。ループする回数も明示しやすいですし。
for文の無限ループ
ちなみに
for(;;)
{
}
と何も書かない事もできます。
が、↑では条件式が入ってないので必ずtrueとして扱われるため
while(true)
{
}
と書くのと同じになってしまい、breakが必要になってきます。
while(true)とfor(;;)のどっちを使うかはお好みでしょうか。breakでループを抜けるような処理を描きたい場合はどちらか好きな方を使えばいいと思います。
<まとめ>
基本的なループ文についてここまでやってきました。いかがだったでしょうか?
ループ文が使えるといろんな事が便利にできるのでぜひ覚えて起きましょう。
ここまで長々とプログラミングの基本的な事を解説してきましたが、まだプログラミングの解説をしたいと思います。プログラミング疲れたって人もいるでしょうが、これが出来るかどうかでやれることに天と地の差が生じるので頑張ってください。
次回は配列について触れてみたいと思います。