スクリプトの初期化処理の順番を制御する

スキルのマスターデータ的なものを読みこむMasterManagerと、所持スキルのコードからマスターを参照して処理を行うPlayerがある場合。
それまで正常に動作していたのに、一旦unityを再起動したらエラーが発生しだした。
MasterManagerとPlayerの初期化を行う際に、どちらもStartで初期化を行っていたんだけど、どうやら再起動前後でその実行順が変わってしまったらしい。

http://docs.unity3d.com/ja/current/Manual/class-ScriptExecution.html
これによると、異なるスクリプト間でのAwakeやStartやonEnableの実行順は不定らしい。
今回はMasterManagerだけは確実に先に実行させたい。
見つけた解決策は2つ。

実行順をExecutionOrderで制御する


スクリプトからExecutionOrderボタンを押すと設定画面が出てくる。
設定方法は前述のhttp://docs.unity3d.com/ja/current/Manual/class-ScriptExecution.html
ここで登録されているものはその順番でAwakeやStartやその他が実行される。
default time内のスクリプト(登録していないスクリプト)の実行順は不定

MasterManagerの初期化をAwakeで行う。

Order of Execution for Event Functions - Unity マニュアル

シーンに追加されたオブジェクトで 全て のスクリプトは Start や Update、その他の関数が呼び出される前に Awake と OnEnable 関数が呼び出されることに注意してください。

とあるので、MasterManagerの初期化処理をAwakeで行えば確実に先に実行される。こっちのほうがスマートな感じ。

どちらでやるべきか。

基本的にそのスクリプト内で完結させられる初期化処理はAwakeで行うべきなんだろう。
他のスクリプトと連携する部分だけStartに持っていって、それでも更に順番を制御したい時だけExecutionOrderで、あくまで例外的な処置として書いていく感じで。

web playerでspriteがボケる問題が解決

unity web player用に出力した時だけボケる - None.
先日の問題の対応策が分かった。

Survive

この記事に書いてある通り、Generate Mip Mapsをoffにすることで解決。
Thanks HIETALAHTI!(読めない)

クッキリした。

Generate MipMapsの効果についてはこっちを参照。
テクスチャ - Unity マニュアル

mipmapはカメラが凄い遠い時とかに使われるものなので、チェックは入ってて生成されても、それだけなら問題なさそうに見える(実際、web player以外のビルドでは問題が無い)。
なぜweb playerだけでこの現象が起こるのかは未調査。

web playerのオフライン対応でもハマっている

先日のボケの原因を調査しようと外でカタカタやろうとしたところ。
web player用にビルドしたhtmlをwebに繋がっていない状態で開くとエラーが出る。


こんなやつ。
どうやらデフォルトで吐かれるhtml(とjs)では、web playerが最新かどうかを自動で見に行こうとするらしい。
そこで繋がらないのでエラー。

http://docs.unity3d.com/ja/current/Manual/PublishingBuilds.html
このページの「オフライン WebPlayer の配置」を見ると、BuildSettingsのOfflineDeploymentをtrueにすれば最新かどうかのチェックをするUnityObject2.jsじゃなくてUnityObject.jsのパスが通って、オフラインでも起動できるようになると書いてある。
んだけど、何度やってもUnityObject2.jsでしか吐かれない。なんだこれ2。

2015/5/27追記

offline deploymentを有効にすると、生成するhtmlで読み込んでいるUnityObject2.jsがunityサーバーからじゃなくてローカルのパスに変わるようだ。
offline deploymentの効果はこれ?
UnityのマニュアルにあるUnityObject.jsじゃなくてUnityObject2.jsなのは、マニュアルの方が古いのかもしれない。
結構前にUnityObject.jsからUnityObject2.jsに変わったはず。
で、そこまではわかって、UnityObject2.jsを追いかけてみるも状況は変わらず。面倒になってきた。

unity web player用に出力した時だけボケる

sprite shaderにちょっと手を加えたものを使って2Dのゲームを作り中。

ずっとunity上でだけ動かしてたので、そろそろと思ってweb playerに出力したらなぜかボケる。

unity上と

web player。ボケる。
ちなみに、macスタンドアロン用に出力した場合はボケない。
解像度を弄ったりsprite画像のformat設定を弄ったりしても変化無し。なんだこれ。わからん。

2015/5/29追記

対応策を見つけたので記事書いた。
web playerでspriteがボケる問題が解決 - None.

衝突したGameObjectのComponentにアクセスする。

衝突した、というかほかのGameObjectのComponentにアクセスする方法。
GetComponentで持ってくる。
衝突したオブジェクトのEnemyComponentのプロパティ、pointにアクセスする場合。

void OnTriggerEnter2D(Collider2D c) {
  c.gameObject.GetComponent<Enemy>().point;
}

PrefabをGUIで複製する。

スクリプトからPrefabを作る方法はあるっぽいけど、今回はそれじゃなく、Prefabを普通にGUIでコピペする方法。
普通にCtrl+Cとか右クリックで出来るだろうと思ったら出来なかった。

今のとこ見つけた方法は二つ。
まずは一旦シーン上にインスタンスを作って、別のPrefabとして登録する方法。
同じ名前なら「名前 1」と勝手に変わるので重複はしない。

もう一つは、空のPrefabを作ってそこに入れる方法。
ProjectビューでCreate → Prefabを選択。適当な名前をつける。
空のPrefabはアイコンが白い。

コピーしたいPrefabをドラッグ&ドロップ。
アイコンが青に変わり、EnemyがBossに複製された。

Layerごとの衝突判定有無を設定する。

壁で跳ね返るようになったので大量にオブジェクトを配置してみた。

が、このままではオブジェクト同士でも衝突してしまう。
そこで今回は、Enemyオブジェクト同士では衝突しないようにしてみる。

Edit > Project Settings > Tags and Layersを選択

EnemyのPrefabで、LayerをEnemyに変更。

Edit > Project Settings > Physics2Dを選択。
Layerごとの衝突判定有無を設定する。

左右の壁と床では反射し、Enemy同士では衝突しないようになった。