devlog [naru design]

プログラミングやテクニカルな内容の覚え書き。

Unity5からシェーダーまわりがガラッと変わりました。よりリアルな質感を表現するためにStandard Shaderが汎用的に使われます。新規でマテリアルを作成した時や、3Dオブジェクトを作成した時、fbxでオブジェクトをインポートした時には、このStandard Shaderがデフォルトで設定されます。

平面オブジェクトにStandard Shaderを設定した時に、想像していなかった状態になったので、ここにメモしておきます。

現象

以下の画像はGameウィンドウのキャプチャです。平面オブジェクトにStandard Shaderを割り当てています。ライトはDirectional Lightを1つシーンに設定しています。画像を見ると、平面の中央がライトが直接あたっているように白くなっています。
スクリーンショット 2015-03-16 23.20.42

シーンの構成はカメラの前面に平面オブジェクト、やや上の方にDirectional Lightを配置しています。平面の中央に直接ライトはあてていません。

スクリーンショット 2015-03-16 23.18.19

平面オブジェクトに設定しているStandard Shaderはデフォルトの状態です。

スクリーンショット 2015-03-16 23.17.28

結論

Standard ShaderのMain MapsのSmoothnessが影響していたようです。この値を0に設定したら以下画像のようにフラットな質感になりました。

スクリーンショット 2015-03-16 23.21.49

平面オブジェクトの質感がおかしい*1、妙にバンディングが目立つ時は、このパラメータが影響しているかもしれません。

Unity5.0

追記(2015/04/23)

*1 「質感がおかしい」は正しくない。ここでは、フラットな設定にしたかったのにライトが写り込んでしまったのを何とかしたかっただけ。Smoothnessはメタリック、マット感をコントロールするためのパラメータ。メタリックになると背景の映り込みやライトによるハイライトが発生するので挙動は問題ない。

Smooothnessを小さくするとマットな質感になり、背景の映り込みやライトによるハイライトが無くなっただけ。

リアルタイムに影をつけるのは負荷がかかります。カメラからどれぐらい離れた所まで影を計算するか(表示するか)を設定することが出来ます。

設定は、(メニュー)Edit-Project Setting-Qualityで表示されるQuality SettingウィンドウのShadow Distanceです。

shadow_distance

以下、Shadow Distanceの値による違い

Shadow Distを7に設定

Shadow Distanceを7に設定

Shadow Distanceを20に設定

Shadow Distanceを20に設定

影の表示をONにしているのに表示されない場合は、Shadow Distanceの値を変更すると解決するかも。

Unity5.0

Inspectorに表示したいプライベート変数の前に[SerializeField]と記述する。

調整が必要な値はハードコーディングせず、プライベート変数として作成し、SerializeField属性を指定しておくと良いと思います。

※ public変数にすればInspectorパネルに表示されますが、他のコンポーネントから操作できてしまう。

スクリプトを編集&更新するとUnityエディタに戻った際に若干の待ち時間(スクリプトを再コンパイルしてる?)が発生します。Inspectorパネルで値を変更できるようにしておけば、待ち時間なくプレビューを開始できるので作業効率が上がると思います。プレビュー時に値を変更して挙動を確認することも出来ます。ただし、プレビューを終了すると値は元に戻ってしまいますが…。

先のパーティクル発生制御を実装していた時のスクリプトで気になる点を発見。

Awake()で、inactiveなBalloonオブジェクトのParticleSystemコンポーネントを取得しています。
あれ?inactiveなオブジェクトをFindしたらNullじゃなかったっけ??
GameObject.Find()では間違いなくNullになっていたはずだけど…。

改めてスクリプトのリファレンスでTransform.Findを調べてみました。

Transform.Find

http://docs.unity3d.com/ScriptReference/Transform.Find.html

ちなみにGameObject.Findは

GameObject.Find

http://docs.unity3d.com/ScriptReference/GameObject.Find.html

よく見るとGameObject.Findの説明には

”This function only returns active gameobjects.”

と書かれています。Transform.Findには、この一文がありません。今まで、Find()ではinactiveなオブジェクトを取得できないと思っていましたが、違っていたようです。

– GameObject.Find() : activeなオブジェクトのみ
– Transform.Find() : active/inactiveどちらでも

また、Transform.FindChild()はリファレンスには見当たりません。以前から変だなと思っていましたが、Transform.FindChild()はTransform.Find()と同等なようです。リファレンスに載っていないのでFindChildは使わないほうがいいかもしれません。

ParticleSysmte.Play()を何度か繰り返し呼び出すとパーティクルが発生しなくなる不具合に遭遇。
Unity上では問題なく動いていたが、実機(iPhone)で動かすと不具合が発生する。

問題の発生したスクリプト

検索でUnityAnswersに以下の投稿を発見。

ParticleSystem.Play() does not play particle.

http://answers.unity3d.com/questions/513517/particlesystemplay-does-not-play-particle.html

上記を参考にしてスクリプトを変更。

変更後のスクリプト

パーティクルの発生をPlay()ではなく、(Play on Awakeを有効にした上で)ゲームオブジェクトがEnableになった時に行うように変更。実機で動作を確認、不具合が解消された模様。

Unity4.5.0f6

一斉に風船が飛んで行くイメージをパーティクルで作ってみました。

設定は以下の様な感じ。

スクリーンショット 2014-12-20 1.56.53

RendererのMaterialに、Mobile/Particles/Alpha Blendedシェーダー(風船のPNG画像を適用)で作ったマテリアルを適用してます。

iPhoneクラスのgenerationプロパティからデバイス情報を知ることができます。

Debug.Log(iPhone.generation);

特定の機種を判別したいときには

※判別可能なデバイスは、ドキュメントのiPhoneGenerationを参照

スクリーンサイズからデバイスを判定する方法は
Unity3D:iOSデバイスの判定

ほとんど触っていなかった Shuriken でクラッカー風のパーティクルを作ってみました。

設定は以下の様な感じ。

スクリーンショット 2014-12-11 16.03.38