投稿

ラベル(NGUI)が付いた投稿を表示しています

[Unity]NGUIでUnityの2Dスプライトをアニメーションする

イメージ
NGUI で Unity 4.3 の 2D スプライトを使う方法は [Unity]NGUIでUnityの2Dスプライトを使う に書きましたが、今回はこれをアニメーションさせる方法です。 NGUI のバージョンは 3.0.6f6 以降が必要です。 まずは上記記事などを参考に、Unity 4.3 の 2D スプライト表示とアニメーション、NGUI で Unity の 2D スプライト表示ができるところまで準備してください。 あとは SpriteRenderer と Animator をアタッチして、数行のコードを追加すれば完成です。(空のオブジェクトに下のコードだけアタッチすれば、必要なスクリプトは全てアタッチされます。) コードは以下。(  GitHub : unity-ngui/UI2DSpriteAnimation.cs  ) using UnityEngine; using System; [RequireComponent(typeof(UI2DSprite))] [RequireComponent(typeof(SpriteRenderer))] [RequireComponent(typeof(Animator))] public class UI2DSpriteAnimation : MonoBehaviour { System.WeakReference spriteRenderer_ = new System.WeakReference(null); SpriteRenderer spriteRenderer { get { return (spriteRenderer_.Target ?? (spriteRenderer_.Target = GetComponent<SpriteRenderer>())) as SpriteRenderer; } } System.WeakReference ui2dSprite_ = new System.WeakReference(null); UI2DSprite ui2dSprite { get { return (ui2dSprite_.Target ?? (ui2dSprit...

[Unity]NGUIでUnityの2Dスプライトを使う

イメージ
Unity 4.3 で 2D スプライト機能などが強化されましたが、GUI 向けではないということで、現状 GUI は NGUI などのアセットを使うのがよいようです。 Unity の 2D スプライトと NGUI を併用する方法は少なくとも 2 種類、それぞれ独立させる方法と NGUI に取り込む方法がありますが、今回は後者について紹介します。 前提として、Unity の 2D スプライトの表示方法は把握していることとします。( [Unity]Unity4.3の2D機能入門まとめ  ã‚‚どうぞ。) NGUI は 3.x ç³» (アニメーションも考えると 3.0.6f6 以降) を使ってください。 NGUI で Unity の 2D スプライトを表示するには、 UI2DSprite  ã‚’使うだけと簡単です。 いつも通りメニューから NGUI -> Create -> 2D UI として UIRoot などを作成したあと、NGUI -> Create -> Unity 2D Sprite します。 あとはスプライトをインスペクタにドラッグ&ドロップするだけ(下図)。 これで NGUI と座標系やサイズを共有し、NGUI のイベント処理も使えるようになります。 Unity のスプライトアニメーションとも連携できます。方法はこちら(  [Unity]NGUIでUnityの2Dスプライトをアニメーションする  )。 NGUI の更新情報はこちら。 ゲームは初心者にやさしく: NGUI 3.0.6 リリース ゲームは初心者にやさしく: NGUI チュートリアルビデオ(3.0.6 対応で最新化!) 2013/12/9 追記 :  [Unity]NGUIでUnityの2Dスプライトをアニメーションする  ã‚’書きました。

[Unity]NGUIで当たり判定を付ける

NGUI でスプライトに当たり判定を付ける場合、普通に スプライトに Collider を付ける 必要に応じて RigidBody も付ける OnCollisiionEnter などを書く とした上で、 RigidBody の FreezePosision の z と FreezeRotation の x, y にチェック(負荷が減る、と思う) 表示順の制御に z 座標を使っている場合、衝突し得るように Collider の Size.z などを調整 クリック等のイベントを受け取るスプライトの Collider は最も手前になるようにする または、イベントを受け取るスプライトを含む UIPanel のレイヤを分け(スプライト個別にはレイヤを変更できないため UIPanel 単位になる)、UICamera の Event Receiver Mask をそのレイヤだけに、Camera の Culling Mask はそのレイヤも表示するようにする あたりに気を付けるとよさそうです。 複数のスプライトが他のオブジェクトの子である場合などは、Collider は各スプライトに付け、イベントは親オブジェクトで処理(スプライト側で一旦受けて親に SendMessage)するのもよいかもしれません。 3D 用の衝突判定を 2D で使うのは富豪的な気もしますが…

[Unity]NGUIのOnDragイベントを使う

NGUI のスプライトをドラッグで動かせるようにしたときのメモです。 (2013/5/9 追記 : 動かすだけなら UIDragObject だけで済みます。こちらはコーディング不要です。) スプライトに Collider をつけた上で、 public class Player : MonoBehaviour { void OnDrag(Vector2 delta) { Vector2 mousePoint = UICamera.lastTouchPosition; Vector2 worldPoint = UICamera.currentCamera.ScreenToWorldPoint(mousePoint); transform.position = new Vector3(worldPoint.x, worldPoint.y, transform.position.z); } } または public class Player : MonoBehaviour { void OnDrag(Vector2 delta) { Vector2 mousePoint = UICamera.lastTouchPosition; Vector2 worldPoint = UICamera.currentCamera.ScreenToWorldPoint(mousePoint); // 普通は毎回 Find() しない transform.localPosition = GameObject.Find("UI Root (2D)").transform.InverseTransformPoint(new Vector3(worldPoint.x, worldPoint.y, 0)); } } などですね。 引数の delta はスクリーン座標上での前回のマウス位置との差分(だと思う)なので、UIRoot の Scaling Style を Pixel Perfect にしていない限りはそのままでは使いにくそうですね。 2013...

[Unity]NGUIでスプライトを隙間なく並べる

イメージ
NGUI で 2D ゲーム風にドット絵のマップチップを敷き詰めた時などに、スプライト間に 1px 程度の隙間が空いてしまう場合の確認内容です。 テクスチャの Filter Mode を Point にする 元画像を周囲 1px 拡大しておく(TexturePacker を使っているなら、Layout の Extrude を 1 にするだけで簡単にできます)

[Unity]NGUIで画面サイズに合わせる(NGUI2.3.0対応版)

以前 [Unity]NGUIで画面サイズに合わせる(その2) で書いたスクリプトが、NGUI 2.3.0 の変更との兼ね合いで正しく動かなくなっていたので、今更ですが対応版です。 UIRoot.automatic が obsolete 扱いになり、代わりに scalingStyle というパラメータに変更になったようです。 PixelPerfect : 拡大縮小しない(automatic = true 相当) FixedSize : 画面の高さに合わせる(automatic = false 相当) FixedSizeOnMobile : iOS, Android のときは FixedSize、それ以外では PixedPerfect 横がはみ出ないように画面の幅に合わせる機能は現在でもないようですね。 というわけで、数行しか変わっていませんが 2.3.0 対応版です。 using UnityEngine; [ExecuteInEditMode] public class UIRootScale : MonoBehaviour { public int manualWidth = 1280; public int manualHeight = 720; UIRoot uiRoot_; public float ratio { get { if(!uiRoot_){ return 1.0F; } return (float)Screen.height / uiRoot_.manualHeight; } } void Awake() { uiRoot_ = GetComponent<UIRoot>(); } void Update() { if(!uiRoot_ || manualWidth <= 0 || manualHeight <= 0){ return; } int h = manualHeight; float r = (float...

[Unity]NGUIで画面サイズに合わせる(NGUI2.2.2対応版)

2013/5/4 追記 : スクリプトは [Unity]NGUIで画面サイズに合わせる(NGUI2.3.0対応版) が最新です。 以前 [Unity]NGUIで画面サイズに合わせる(その2) で書いたスクリプトが、NGUI のバージョンアップによる機能追加との兼ね合いで正しく動かなくなっていたので、その暫定対応版です。 NGUI 2.2.2 : http://www.tasharen.com/forum/index.php?topic=11.msg9404#msg9404  ã« - NEW: You can now specify a minimum and maximum height on UIRoot. とある通り、UIRoot に minimumHeight と maximumHeight が追加されました。ソースのコメントより If the screen height goes below this value, it will be as if 'automatic' is turned off with the 'manualHeight' set to this value. とのことで、画面サイズが minimunHeight を下回った場合に画面サイズに合わせて縮小するのを諦めてはみ出させたり、maximumHeight を上回った場合に拡大するのをやめて余白を作るための機能のようです。 この条件下で以前のスクリプトが正しく動かなくなっていたので、取り急ぎこの機能追加を実質無視するような方向での対応を加えたものが以下です。 using UnityEngine; using System.Collections; [ExecuteInEditMode] public class NGUIUtilScalableUIRoot : MonoBehaviour { public int manualWidth = 1280; public int manualHeight = 720; UIRoot uiRoot_; void Awake() { uiRoot_ = GetComponent<UIRoo...

[Unity]NGUIで画面サイズに合わせる(その2)

イメージ
2013/5/4 追記 : スクリプトは [Unity]NGUIで画面サイズに合わせる(NGUI2.3.0対応版) が最新です。 NGUI での複数解像度対応のための画面全体の拡大縮小は以前  [Unity]NGUIで画面サイズに合わせる  ã«æ›¸ã„た方法もありますが、今回は別の、より NGUI の枠組みを活用したやり方でやってみます。 実は NGUI 自体にも画面サイズに合わせて拡大縮小する機能は一応あって、UIRoot の manualHeight がそれに当たります。manualHeight は、 この高さが画面の高さにちょうど収まるようにする という意味があります。(少なくともそういう挙動をします。 公式ドキュメント には特に説明はないのですが) デフォルトでは Automatic=true になっているため、画面サイズの変更に合わせてこの manualHeight も自動で値が変わるようになっていますが、Automatic=false にすることで値を固定できます。ここで 240 にすると、下図のように 320x240 のスプライトがちょうど収まるようになります。 しかし、左右が余る場合はよいのですが、上下が余ってほしい場合でも下図のような表示になってしまいます。 というわけで、次のスクリプトを UIRoot に追加して、上下が余ってほしい場合に manualHeight を制御するようにしてみます。 using UnityEngine; using System.Collections; [ExecuteInEditMode] public class NGUIUtilScalableUIRoot : MonoBehaviour { public int manualWidth = 320; public int manualHeight = 240; UIRoot uiRoot_; void Awake() { uiRoot_ = GetComponent<UIRoot>(); } void Update () { if(!uiRoot_ || manualWidth <= 0 || manualHeight <= 0){ re...

[Unity]NGUIの複数パネル時のDrawCallメモ

イメージ
NGUI の複数パネル時の DrawCall について、個人的に勘違いしていたのでメモ。 UIPanel を増やすと同じ Atlas を使っていても DrawCall が増えると思っていたのですが、そうでもないようです。 図の Panel2(緑) と Panel3(青) は同じ Atlas です。以下の図では、Panel1(赤、別 Atlas)が 2 と 3 の間の Z 座標になっていて、合計の DrawCall は 3 になっています。 一方、以下の図は Panel1 の Z 座標は 2 と 3 よりも奥になっていて、合計の DrawCall は 2 になっています。ソースまでは確認していませんが、おそらく同一 Atlas かつ間に他の Atlas を描画する必要のない 2 と 3 をまとめて描画してくれていると考えられます。 (NGUI の複数 Atlas 時の表示順序については [Unity]NGUIのDepth設定その2(複数Atlas) を参照) NGUI のバージョンは v2.0.9a です。 公式ドキュメント ( NGUI: UIPanel » Tasharen Entertainment ) にはパネルを増やすと DrawCall が増えるように読める記述が見られる気がしますが、まとめてくれるならありがたいですね。

[Unity]NGUIのDepth設定その2(複数Atlas)

イメージ
NGUI で複数の Atlas 利用時には、前後関係は Depth ではなく Z 座標で決まるというのは以前 [Unity]NGUIのDepth設定 に書いたのですが、これが結構くせがありました。 単一の Widget 同士なら単純に Z 座標が小さいほうが手前になりますが、複数の場合 「同一 Atlas の Widget の Z 座標の平均値」が小さいほうの Widget 全てが、もう一方の全てより手前になる ようです。 上図で、SciFi Label 1, 2 と Fantasy Label 1, 2 はそれぞれ同じ Atlas を利用しています。Fantasy Label 1 は Z=1 と 4 つの中で最も Z 座標が大きいですが、Fantasy Label 2 が Z=-3 であるため平均は Z=-1、一方の SciFi Label 1 と 2 の平均は (0 + -1)/2 = -0.5 となり、Fantasy Label 1 も SciFi Label 1, 2 より手前になっています。 普通は「手前 : Fantasy 2 > SciFi 2 > SciFi 1 > Fantasy 1 : 奥」を期待すると思うんですけどね。ちなみに、上の状態で DrawCall=2 です。 では、期待通りにするにはどうするかと言うと、一つは Panel の Depth Pass にチェックを入れることです。…が、アルファブレンディングが犠牲になる上に DrawCall=4 になるため、これは正直使わないと思います(そもそも用途が違いそう)。 結局、Panel を増やすことで、下図のような表示を得ることができました。DrawCall=3 です。 なお、ここでは Panel だけ Z 座標を順序付けし、Widget の Z は全て 0 にしています。実際の表示順序は各 Panel 配下の Widget の絶対 Z 座標の平均で決まるため、上図で Fantasy 1 の Z を -3 にしたり、Panel 1 にもう一つ Widget を追加して Z=-5 にすると、Fantasy 1 が一番手前になります。   NGUI のバージョンは v2.0.9a でした。 おまけ 検証中に、あるオブ...

[Unity]NGUIで画面サイズに合わせる

2012/8/24 追記 : 以下、おいそぎの方は [Unity]NGUIで画面サイズに合わせる(その2) の方がおすすめです。 NGUI で複数解像度対応のために、画面サイズに合わせて拡大縮小するスクリプト。 Panel に追加して、インスペクタで Base Object に画面サイズの基準となる GameObject (例えばデフォルト 1280*720 で作っているなら、そのサイズの GameObject) をドラッグ&ドロップすれば使えます。 using UnityEngine; using System.Collections; public class ScreenScaler : MonoBehaviour { public GameObject baseObject; public bool aspectFit = true; void Update(){ Vector3 ratio = new Vector3( Screen.width / baseObject.transform.localScale.x, Screen.height / baseObject.transform.localScale.y, 1.0f ); if(aspectFit){ if(ratio.x > ratio.y){ ratio.x = ratio.y; } else if(ratio.y > ratio.x){ ratio.y = ratio.x; } } transform.localScale = ratio; } } 起動中に画面サイズの変更がないなら、Update() でなく Start() でやってしまったほうがよいです。 Aspect Fit = true だと異なるアスペクト比のディスプレイで上下か左右が余ります。この部分の塗りつぶし色を変更したい場合は、Camera の Clear Flags を Solid Color にして ...

[Unity]NGUIのDepth設定

Unity&NGUIはじめました これまで、フルスクラッチでマルチプラットフォーム対応の2Dゲームエンジンを作ろう!と細々やってきたりしたのですが、多少は動くけどまだまだ時間かかるな、というところで 3D ゲームエンジン Unity とその 2D 用プラグインの一つ NGUI に出会ってしまったのでした。 マルチプラットフォーム対応 スクリプト言語利用可 ネイティブコードも利用可 必要に応じて拡張可 開発するゲームのジャンルにとらわれない  ã¨、自分で作ろうとしていたものがほぼカバーされてしまっているようだったので、名残惜しい気持もありつつも  Unity&NGUI に乗り換えてみることにしました。 NGUI の Depth 設定 さて、NGUI でスプライト同士の前後関係は通常 UIWidget の Depth で決まるのですが(大きいほど手前)、この順序関係が適用されるのは同一の Atlas を利用したスプライト間だけで、異なる Atlas を利用したスプライト同士では Depth 通りの順序になりません。 異なる Atlas を利用したスプライト同士の順序を決めるためには、Depth ではなく Z 座標 を使います(小さいほど手前)。(2012/7/4 追記 : Z 座標の平均値 依存という妙な挙動でした。詳細は [Unity]NGUIのDepth設定その2(複数Atlas) に書きました。) …というのは公式の NGUI Tutorial: Step 2 に普通に書いてあるのですが、NGUI をいじってみる前に流し読みして分かったつもりになっていたので見逃してしまっていました。 ただ、Z 座標を操作すれば異なる Atlas を利用したスプライトを混在させられるものの、Atlas を増やすとその分だけ DrawCall が増える -> モバイルでの動作が厳しくなるようなので、なるべく一つにまとめたほうがよさそうです。 DrawCall を増やさずにリソースを分割したりできるか、逆に何も考えずにひたすら一つにまとめていいのか、などはまだ調査中です。 ちなみに、Atlas 用画像の生成には テラシュールウェア さんで紹介されていた TexturePacker...