最小の Unity プロジェクト

Unity はプロジェクトを構成する要素が意外と少ないです。そもそも中核となるプロジェクトファイルのようなものがない。

Unity 2017 では、新規プロジェクトを作成すると次のようなディレクトリが作成されます。

├Assets/
├Library/
│└いろんなふぁいる
├ProjectSettings/
│└いろんなふぁいる
├UnityPackageManager/
└ProjectName.sln

Assets/ にはモデルやテクスチャ、音源やスクリプト、具体的なシーンデータといった、実際にアプリケーション内で利用するファイルが入ります。Library/ はキャッシュ的な何かが入るらしいです。これはコミットしない。ProjectSettings/ はビルドやグラフィック設定、Unityのバージョンなど、ゲーム全体の設定に関するファイルが入ります。UnityPackageManager/ はよく知らないけど、パッケージ用のなにかでしょ(適当)ProjectName.sln は VisualStudio 用のファイルですね。

ここから Unity Editor がプロジェクトであることを認識する最小構成までファイルを減らすとこうなります。

├Assets(空ディレクトリ)/
└ProjectSettings/
 └ProjectSettings.asset

なんとたったこれだけで Unity プロジェクトであると認識してくれます。

Unity の MonoBehaviour と Coroutine

やってみて当たり前だと気づいたのですが、StartCoroutine を使うには、MonoBehaviour を継承している必要があります。

つまり、これはダメ

public class MyAwesomeClass {
  void BestMethodEver() {
    StartCoroutine(SomeCoroutine());
  }
}

どうしても使いたかったら、ちゃんと MonoBehaviour を継承するか、

public class MyAwesomeClass : MonoBehaviour {
  void BestMethodEver() {
    StartCoroutine(SomeCoroutine());
  }
}

StartCoroutine を呼ぶ依代を探します。

public class MyAwesomeClass {
  void BestMethodEver() {
    Yorishiro yorishiro = GameObject.Find("Yorishiro").GetComponent<Yorishiro>();
    yorishiro.StartCoroutine(SomeCoroutine());
  }
}

Unity は、シングルスレッドでの動作が基本で、Coroutine もシングルスレッドで動作します(ちょうど、Node のような感じ)。StartCoroutine で呼び出せば、ちゃんとゲームループと同じメインスレッドで動いてくれるので、自分で Coroutine を実装するよりは、↑のような方法で解決するほうが良さそうです。

Unity のスクリプトの実行順を設定する。

Unity では、MonoBehaviour に設定した Update や LateUpdate は順不同で呼び出される。

これらの順番は、メニューの [Edit] → [Project Settings] → [Script Execution Order] を開き、各スクリプトの優先順位を数値で指定することで、制御することが出来る。 ただし、同じクラスのインスタンス同士の実行順は制御できないので、その場合は管理するためのクラスなどを用意する必要がある。

Script Execution Order は、各スクリプトの meta ファイルに保存されるため、パッケージの Export などをしても引き継ぐことが出来る。

Google Apps Script とロック

恐ろしいことに Google Apps Script(以降 GAS)は並列で実行される。普段 JS を書いていると意識しないが、並列実行ほどプログラムにおいて恐ろしいものはない。

ロックは、以下のような関数で取得できる。

var documentLock = LockService.getDocumentLock();

最大で10秒間待って、ロックを取得するには以下のようなコードを書く。

if (documentLock.tryLock(10000)) {
  // ロックを取得したときの処理
}

取得したロックを解除するには次の関数を呼ぶ。

documentLock.releaseLock();

シートを編集するような処理を書く場合、そもそもロックしなくて良いケースなどレアなので、次のようなコードを脳死で書いておけばいいと思いました。

var documentLock = LockService.getDocumentLock();

if (documentLock.tryLock(10000)) {
  try {
    main();
  } finally {
    documentLock.releaseLock();
  }
} else {
  console.log("failed to aquire lock.");
}

Unity の meta ファイルと guid

本日は Unity のパッケージ読み込みで一日を潰してしまいました。 Unity のプロジェクト上で扱われるリソースは Asset と呼ばれ、 実ファイルと meta ファイルの組で管理されます。

meta ファイルは実ファイルに付加的な情報を与えるものです。 guid やインスペクタで設定するような情報(リグとか)を実ファイルを編集することなく修正することができ、かしこいです。

guid は同一のファイルを識別するために利用されており、 Unity の project 内でファイルを移動しても参照が外れないのはこの仕組のおかげです。

一方で、パッケージを読み込むときなどは、この guid が悪さをすることもあり、 素直に上書きしてほしいのに、guid とバージョニングの問題で上書きしてくれなかったりする。

正直不便なことの方が多い気もする。 git でプロジェクトを管理していると、バージョニングが二重になる。

誰も読まないブログを書く意味

僕は日記というものをつけたことがないし、
社内で日報を続けようとして何度も挫折している人間です。

かく言うこのブログも、以前に毎日書くと宣言して、挫折しているわけですから、
今回もいつまで続くかわからないんですけど、
まあ何事もやらないよりやったほうがいいし、
少しずつでも日々のルーチンを変えるのは悪くないよね、と
そういう心持ちで始めたのですが、
やっぱり、こうも読者の少ないブログともなると、
ある程度、意義というか、目的を決めないと続かない気もするので、
ここにブログを書く目的を立てておこうかと思います。

  • 日本語が下手なのでうまくなる
  • 技術記事は真面目に書けば検索に引っかかるようになるので、種まき
  • 今後なにか新しいことをするために、少しでも自分から情報発信する場を用意しておく
  • Slack の無駄話を減らして業務効率を上げる
  • Unity を Web からほぼゼロで始めるので、同じような人の助けになるような記事を書く

心が折れそうになったらこの記事を見直す。

ブログを書くぞ(決意)

最近は社内の Slack で、もっぱら分報と称し、気づいたことや思ったことを書き留めていたのですが、
やはり、狭いコミュニティで情報を発信するのは、それほど効果的でないし、
せっかく人の目に留まるチャンスがあるのに、それをみすみすと逃すのは、もったいないなと感じたので、
再びブログをちょくちょくと書いていきたいと思います。

直近の報告としては、キャラクターの二面図を描かなくてはいけません。
僕は幼いころに母親に描いた絵を貶されて以来、他人に自分の絵を見せるのが、
本当に怖くてたまらないのですが、理性の力をもってして克服していきたいです。