uGUIの独自の描画処理なんかの記事を書きましたが、改めてuGUIの基本を書きたいと思います。
といってももっといい記事がその辺にいろいろありそうですが…
uGUIでUI作るための準備
スマートフォン向けのUIを作る前提で準備をします。
プロジェクト作る
まずは新規でプロジェクトを作ります。
3Dと2Dの選択がありますが、これはどちらでも構いません。
設定によって新規のシーンを作製したときに初めに配置されているGameObjectの内容が変わったり…といったこまごました挙動の違いはありますが、別に2Dを選んだから3Dが作れなくなるとか、その逆とかはありません。
とりあえずスマートフォン向けに作りたいのでiOS当たりにswitch platformしておきます。
Gameビューの左上から画面サイズを選択できます。
好きなサイズを指定します。
画面のサイズが指定できるだけで別に指定デバイスの挙動をエミュレーションしてるわけではないので注意です。
フォルダを用意しておく
各データやスクリプトを入れるフォルダをプロジェクト内に用意しておきましょう。
別にフォルダを用意しなくても作れはしますが、やはり整理されてないと後々作りにくくなっていきますので整理する癖を。
とりあえずこの3つを
(フォルダは右クリック → Create → Folderで作れます。)
フォルダやファイルの「移動」はUnity上から行いましょう。
Windowsのエクスプローラ等で行うとUnityがファイルの管理が出来ず予期せぬ不具合を生みます。
今回使う画像
適当に用意した丸。
適当に用意したゲージ
適当に用意したスピーカ君
これらをDatasフォルダに入れておきましょう。
(※別におんなじような画像だったらなんでもいいです。)
Canvasを用意する
uGUIではまずCanvasが必要です。
Cavnasはその子供にいるCanvasRendererがついたGameObjectを画面に描画します。
というわけでCanvasを作ります。
これはHierarchyのCreate → UI → Canvasとすると作成されます。
選択するとCanvasとEventSystemの2つのGameObjectが作られると思います。
この内Canvasが前述の画面描画のシステムです。
EventSystemはタッチ等のイベント処理用のシステムです。
Canvasの設定を行う
スマートフォン向けにCanvasの設定を少しいじります。
想定としてはiPhone4S(640 x 960)でぴったし表示され、それより大きいiPhone5等では足りない分は黒い帯が表示されるという感じで。
(いわゆるレターボックス/ピラーボックス)
CanvasについているCanvas ScalerのUI Scale ModeをScale With Screen Sizeへ変更します。
初期値はConstant Pixel Sizeだと思いますが、これはPC向け等の画面サイズが一様な場合に選択します。
スマートフォンのように各機種でサイズがまちまちな場合はScale With Screen Sizeがお勧めです。
Reference Resolutionには対象の画面サイズである640と960を指定します。
Screen Match ModeにはExpandを指定します。
Expandを指定するとレターボックスになります。
Canvasの設定は以上です。
Expand以外について
後でそれぞれ試してみるといいですが、Match Width Or Heightはアスペクト比を維持したまま、横幅か縦幅の指定した方が画面いっぱいになるように拡縮されます。
Shrinkはアスペクト比を維持したまま縦横両方画面いっぱいになるように拡縮されます。
MatchもShrinkも画面いっぱいにするためにはみ出ることがあります。
※確認には下画面のように640×960なImage(白い部分)と四隅に四角を出すとわかりやすいかと。
Main Cameraを少しいじる
Main Cameraは上記のようにClearFalgsをSkybox、CullingMaskをNothingにするのがお勧めです。
レターボックスは黒でということでBackgroundは黒色にしておきます。
とりあえず画像を表示してみる
まずは1枚画像を表示しています。
Canvasを右クリックしUI → Imageを選択します。
Canvasの下にImageが出来るので、SourceImageにスピーカ君をドラッグ&ドロップで指定します。
これで画像が表示されました。
WidthとHeightを指定することで大きさが変更できます。
Set Native Sizeボタンを押すと、WidthとHeightが画像の大きさに自動で設定されます。
また、RotationのZを変更することで回転させることも可能です。
画像の設定を見直す
画像に元画像にないノイズ(斑点…)が出ていると思います。
これは画像の設定によるものです。
Projectのspeekerを選択します。
FormatにCompressedが指定されていると思います。
これは画質をある程度犠牲にして容量を軽減や処理のパフォーマンス向上するという指定です。
3Dのテクスチャに指定する分にはそれなりに見えるのですが、2Dの場合は厳しいです。
(OPTPiX iméstaなんかを使うと圧縮される前提に画像を変換する事で汚さを軽減できますが…※宣伝ではないです)
というわけで16 bitsへ変更しApply(確定ボタン)を押しておきます。これでノイズがなくなると思います。
2Dのものは基本的に16 bitsで良いと思います。
よくあるウインドウ枠を表示する
ゲームに限らずよくあるウインドウ枠を表示します。
こういう幅を変更しても角の丸みが変わらないものをよく見ると思います。
uGUIではこれがお手軽に作れます。
画像の設定する
画像を選択し、SpriteEditorを開きます。
開いたらBorderの値を上図のように調整します。
Imageを作る
先ほどと同様にCanvas右クリックしてUI → Imageを選択し、この画像を設定します。
この状態でWidthとHeightを変更してみて下さい。
角の丸みを保ったまま拡大縮小が行われています。
Border?
上図ではBorderのパラメータで9つに画像が分解されています。
この9つのウチ四隅は幅が変更されても拡縮されません。
同様に左右は横方向に、上下は縦方向に拡縮されません。
真ん中は縦横どちらにも拡縮されます。
分かりにくいですがこんな感じです。
※Borderの設定はImage TypeがSlicedでなければ無視されます。
が、Borderが設定されている場合は自動でSlicedが初期設定として選択されています。
反転表示
Scaleに負数を指定することで反転します。
左の方はScaleのxに-1を指定しています。
文字を表示する
Canvasを右クリックして UI → Text を選択することで表示できます。
大きさ調整
Scaleでのサイズ調整よりFont Sizeで調整したほうが綺麗に文字を出すことができますが、その分メモリの消費量の増加やパフォーマンスの低下がみられます。
リッチテキスト
Rich Textのチェックがついている場合はHTMLのタグのようなものが使用できます。
使用可能なものは
- <b></b>
- 太字
- <i></i>
- 斜体(イタリック体)
- <size=数値></size>
- 文字サイズ変更
- <color=色></color>
- 色変更
のようです。
たとえば「<b>太字</b><i>イタリック</i><size=80>大きい</size><color=red>赤</color><color=#00ff00>緑</color>」と言った具合です。
※ちなみにこのリッチテキストはDebug.Logでも利用できます。
パラグラフ
Alignmentで右寄せ、左寄せなどが指定できます。基準となる場所はpositionとwidthとheightから決まります。
Overflowで文字がwidthとheightからはみ出る場合の処理を指定できます。
Wrapは自動改行されます。Truncateは範囲外が描画されません。
文字に縁取りを表示する
よくある縁取り文字を表示するのもお手軽です。
TextにAdd ComponentでUI → Effect → Outlineを選択します。
あとは色やらを調整するだけです。
※Distanceをいじればわかりますが、これは設定されたGameObjectの描画内容を単色で後ろに4つ描画しているだけです。
Shadow(ドロップシャドウ)も同様です。
ゲージを表示する
これまたゲームでよくあるゲージを表示します。
画像の設定
まず今までの画像と違って1つの画像に2つのパーツが入っていますので、画像の設定を変更します。
Sprite ModeをMultipleに変更し、Sprite Editorを起動します。
あとは、この2つのパーツを囲うようにドラッグして選択します。
左下のPositionで微調整できます。
設定するとこのようにbarの中にbar_0、bar_1と2つ生み出されます。
(bar_0といった名前はSprite EditorのNameで変更できます。)
Imageにはこのbar_0等をドラッグ&ドロップで設定することで各パーツのみを表示できます。
今までと同様にImageを2つ作りbar_0とbar_1をそれぞれに設定します。
また、uGUIではHierarchyで下にある方が手前の表示されますので、これもドラッグ&ドロップで順番を並び替えます。
手前に表示したい枠(BarBgという名前にしました)の方を下にし、ゲージ部分を上に並べています。
座標を調整したらゲージ完成です。
マスキング
表示されている内容の一部を隠したいときがあります。
例えば上のゲージであれば、値が減少したらその分バーを短く表示したいなーというとき等です。
長方形で柄が無ければ幅を変更すればいいのですが、このゲージは丸くてグラデーションがかかっている為それが出来ません。
RectMask2Dを使う
uGUIには2種類マスキングが用意されていますが、とりあえずRectMask2Dを使います。
Maskとの違い
- Maskと違い長方形でしかマスキングできない
- 余計な描画が発生しない為パフォーマンスがいい
- Materialを勝手に変更しない
- ステンシルを使わない
といった感じです。
ただの四角でマスキングするだけならこちらの方がベターです。
設定方法
設定方法は簡単で、まずCanvasに空のGameObjectを作ります。
作り方はCanvasを右クリック → Create Emptyです。
出来たらBar(クリッピング対象)をその空のGameObjectの子供にします。
※前述の描画の順番には気を付けてください。このGameObjectより枠が下になるようにします。
先ほど作った空のGameObejctにAdd ComponentでUI → 2D Rect Maskをつけます。
これだけでマスキングされていると思います。
マスキングされる範囲はRectTransformのwidthとheightです。
バーがRectTransformの範囲(青い枠)で切れてます。
RectMask2DのPivotを設定する
そのままだと真ん中を中心として幅が設定される為、ゲージなんかには使いにくいです。
イメージとしてはwidthを減らしたらゲージが右から削れていく感じがいいのですが、今のままでは左右両方削れます…
こういう時はPivotで行けるかと(0,0.5)に変更して試してみたのですが、正しく描画されませんでした。(Unity5.3.1f1時点)
というわけで以下のスクリプトを用意しました。
using UnityEngine; using UnityEngine.UI; /// <summary> /// Maskにピボットを指定するためのもの /// GameObjectの構成 /// ・MaskAlignment /// └ RectMask2D /// └ 空のGameObject /// ├ マスク対象の各GameObject達 /// ├ マスク対象の各GameObject達 /// : /// /// 1. MaskAlignmentに大元の大きさを指定(子供のGOが入る大きさ) /// 2. RectMask2Dの大きさをマスキングするサイズに指定 /// 3. MaskAlignmentのpivotの数値をもとにマスキングする方向が変わる /// </summary> [ExecuteInEditMode] [DisallowMultipleComponent] [RequireComponent(typeof(RectMask2D))] public class MaskAlignment : MonoBehaviour { /// <summary> /// OffsetとなるGameObject /// </summary> [SerializeField] private RectTransform offset_; /// <summary> /// RectMask2D /// </summary> [SerializeField] private RectTransform mask_; /// <summary> /// 自身のTransform /// </summary> private RectTransform transform_; /// <summary> /// 更新 /// </summary> void Update() { if (offset_ && mask_) { if ( !transform_ ) { transform_ = GetComponent<RectTransform>(); } Rect myRect = transform_.rect; Rect maskRect = mask_.rect; Vector2 pivot = new Vector2( transform_.pivot.x - .5f, transform_.pivot.y - .5f ); // yは上下逆なので- Vector2 offset = new Vector2( (myRect.width - maskRect.width) * pivot.x, -(myRect.height - maskRect.height) * pivot.y ); mask_.localPosition = new Vector3( offset.x - myRect.width * pivot.x, offset.y - myRect.height * pivot.y, 0 ); offset_.localPosition = new Vector3( -offset.x, -offset.y, 0 ); } } }
ヒエラルキーはこのようになります。
MaskLayerがRectMask2D、OffsetLayerは空のGameObjectです。
MaskParentに上記スクリプトを指定します。
コメントにある通りMaskParentの幅とPivotを適宜指定し、インスペクターでoffset_(=OffsetLayer)とmask_(=MaskLayer)をドラッグ&ドロップで設定します。
あとはMaskLayerの幅を変更すると思った通りの動作をさせることが出来ます。
※今回のゲージならMaskParentの幅は256×100、Pivotは(0,0.5)です。
この記事の結果
こんな感じにできてます。
export_uGUITutorial.unitypackage
とりあえず画像出せてそれっぽいウインドウも出せて文字もだせてマスキングもできてでなんとなくは基本はいいのではという事で今回はこれで終わりです。
そのうちuGUIの別の機能を紹介するかも。
コメント
[…] uGUIの基本の基本 […]
[…] uGUIの基本の基本 […]