初心者とは誰か。俺だ。いや僕です。
なんていうかその都度その都度つまんでいるような感じで進んできてしまっているので、一度まっとうな道に戻りたい。
ひとまず基本的なところとか覚書のように書いていきます。
Unityの環境構築
Unity公式サイトより「Download」へ進んでダウンロード。
WindowsとMacに対応していますね。
Androidアプリ開発するならWinでもMacでもどっちでもだけど、iPhoneアプリならMac一択になりますからこれから用意するなら必然的にMacになるかもしれない。mac miniとかでひとまず十分。
インストーラーはそのまま順を追ってセットアップ。
5.2.0から途中でVisualStudioをインストールするかどうかを聞いてくるので、お好みで。
個人的にはVSのエディタでも良いかなあ。
ただしインストールされるのはVS Communityなので会社とかで使うときは注意ですね。
開発言語
開発言語はC#、JavaScript、Booから選べます。
どれかに決めないといけないと言うより、スクリプトファイル単位で決めていればいい感じ。
だから混合もいける。いけるが、本当に大丈夫かはしらない。
個人的にはC#が好きなのでC#でいきます。
C#の文法などは基本そのままなので割愛。
C#をやったことなくても他の言語の経験があれば困らないかなとは思いますが、文法などについては独習C#あたりを一冊手元に置いておくとよいかもしれない。
加えてUnityで特殊だと思うところ。
コルーチン
コルーチンというのはyieldをUnity独特の扱いにしている感じ。
yieldというのはC#のイテレータ構文で、なんていうか動的なイテレータを作るような挙動をする。
例えば、
int[] list = new int[] { 1, 2, 3, 4, 5 }; foreach(int no in list) { Debug.Log("no: " + no); }
みたいなコードは、
no: 1 no: 2 no: 3 no: 4 no: 5
というような出力になる。
これはforeachがlistの値を一つづつ取ってきているからなんですが、ここで
public IEnumerable getList() { int no = 100; yield return no++; yield return no++; yield return no++; yield return no++; yield return no++; }
という、IEnumerableを戻りとしたメソッドを作り、それを
foreach(int no in getList()) { Debug.Log("no: " + no); }
というように配列の代わりに渡すと、
no: 100 no: 101 no: 102 no: 103 no: 104
というように、yieldで返しているところで、値として取れてきます。
Unityではこれをコルーチンと呼ぶ機能で使用しており、IEnumeratorを戻り値としたメソッドをStartCoroutineに渡すと、今の処理の流れとは別に、yieldまでを毎フレーム実行するようになります。
内部的には、先の例のforeachが毎フレームの処理としてやられている、というところでしょうか。
そして、毎フレームUnityの制御になっているので、マルチスレッドのように見えてその実は違うという、擬似マルチスレッドになっています。
これだけでも面白いのですけど、さらに今いるメソッドの戻りをIEnumeratorとして定義し、yield return StartCoroutine() という形で処理したいメソッド呼び出すと、そのコルーチンの処理が終わるまでそこで処理が停まっているように見えます。
メインループは生きているのでアプリがフリーズしているわけではありません。
これはyieldの入れ子みたいなもので、StartCoroutineで指定したメソッドのイテレータを処理し終えるまでそれを取り出して回し続けている状態だと思われます。
void Start () { StartCoroutine(list1()); } public IEnumerator list1() { int no = 100; Debug.Log("no: " + no); no++; yield return null; Debug.Log("no: " + no); no++; yield return null; Debug.Log("no: " + no); no++; yield return null; // ここでlist2の処理をする yield return StartCoroutine(list2()); // ここから先はlist2の処理が終わってからになる Debug.Log("no: " + no); no++; yield return null; Debug.Log("no: " + no); no++; yield return null; } public IEnumerator list2() { int no = 200; Debug.Log("no: " + no); no++; yield return null; Debug.Log("no: " + no); no++; yield return null; Debug.Log("no: " + no); no++; yield return null; Debug.Log("no: " + no); no++; yield return null; Debug.Log("no: " + no); no++; yield return null; }
この結果は次のようになります。
no: 100 no: 101 no: 102 no: 200 no: 201 no: 202 no: 203 no: 204 no: 103 no: 104
list2の処理が終わってからlist1の処理が再開しています。
ポイントは、これが「毎フレーム、yeildまで」実行されているところで、つまりはフレーム単位で同期が取れることに。フレームで処理をすすめる、みたいなことをやるときには使えるかな。
あと、通信を行うときにyield return StartCoroutineをかけると、通信が終了してから次に進むので、別スレッドを立てて見張る、ということをしなくてもよくなり処理の流れが書きやすくなります。
yieldは結構頻繁に目にすることになると思います。そういうものがある、ということだけでも知っておく感じで。
そうそう、StartCoroutineはMonoBehaviourを継承していないと使えないので注意です。
GameObject
Unity上のオブジェクトはこれに集約されています。
Hierarchyにあるものというのはわかりやすいでしょうか。
基本的にはこのGameObjectと、それに付随するスクリプト、という形でデータの管理を行っていきます。
MonoBehaviour
Unity実行時のオブジェクトやスクリプトはこれを基底としています。