Google

2012年10月29日月曜日

Unityでコインゲー開発:NGUIの活用

Unity開発における画面話の続きです。
今回はUnity勉強会で発表した内容の1つを少し掘り下げて紹介。

以前NGUIとTexturePackerの組み合わせ話を書きました。
NGUIは素晴らしく便利なのですが、使い方にはルールがあります。
UIButtonやUIPanel等、FWが指定したクラスから派生し、かつメニューから順序良く生成していくのが一応の決まりです。
仕方ないと思いつつも、現場ではこのようなニーズがありました。

  自分で作った階層構造付きのオブジェクトにNGUIを適用したい

それぞれ子供のパーツがアニメーションもしたりします。
当たり前ですが、子供のテクスチャをアトラスで効率化するということも必須です。
そんな場合にどうするか、という事で出た答えがこれ。

  サポートするクラスを新規で作ればOK

UIAtlusの考え方は有効で、最初からUnityにあってもいいんじゃない?って感じの設計です。
作りも簡単で修正もできるので、有効活用するクラスを書くのもどうにかなったりします。
で、それをやってくれる今回のソースがこちら。


using UnityEngine;
using System.Collections;
public class PackageTextureUtil : MonoBehaviour
{
public UIAtlas atlas;
public string spriteName;
public void ChangeTexture()
{
if(atlas == null || string.IsNullOrEmpty(spriteName))
return;
MeshRenderer renderer = gameObject.GetComponent<MeshRenderer>();
if(renderer == null)
return;
UIAtlas.Sprite sprite = atlas.GetSprite(spriteName);
if(sprite == null)
return;
Vector2 textureSize = new Vector2(atlas.texture.width, atlas.texture.height);
Vector2 offset = new Vector2(
sprite.inner.x / textureSize.x,
(textureSize.y - sprite.inner.y - sprite.inner.height) / textureSize.y
);
Vector2 scale = new Vector2(
sprite.inner.width / textureSize.x,
sprite.inner.height / textureSize.y
);
renderer.material.mainTexture = atlas.texture;
renderer.material.mainTextureOffset = offset;
renderer.material.mainTextureScale = scale;
}
public void ChangeSharedTexture()
{
if(atlas == null || string.IsNullOrEmpty(spriteName))
return;
MeshRenderer renderer = gameObject.GetComponent<MeshRenderer>();
if(renderer == null)
return;
UIAtlas.Sprite sprite = atlas.GetSprite(spriteName);
if(sprite == null)
return;
Vector2 textureSize = new Vector2(atlas.texture.width, atlas.texture.height);
Vector2 offset = new Vector2(
sprite.inner.x / textureSize.x,
(textureSize.y - sprite.inner.y - sprite.inner.height) / textureSize.y
);
Vector2 scale = new Vector2(
sprite.inner.width / textureSize.x,
sprite.inner.height / textureSize.y
);
renderer.sharedMaterial.mainTexture = atlas.texture;
renderer.sharedMaterial.mainTextureOffset = offset;
renderer.sharedMaterial.mainTextureScale = scale;
}
}


簡単に解説行きます。
このクラスは、アトラスを自前で指定したいGameObjectに追加で入れて使って下さい。
GameObjectには複数のMonoBehaviourが割り当てできるので、動き等のみを実装したクラスと別個につけることも可能です。
やれることはこんな感じ。

  • UIAtlusで設定したアトラスを自前オブジェクトに反映できる
  • 自インスタンス単体でも、マテリアル全体でも適用可能
まずメンバ変数が2つあります。
1つ目はアトラスが貼られているUIAtlusのプレハブをD&Dで指定して下さい。
2詰めはNGUIの特徴である、アトラス指定の文字列情報。
これは以前TexturePackerでやりましたが、ファイル名から拡張子を抜いたものがそのまま指定できるという便利なものです。
この仕組みのお陰で指定が非常に楽になるはずです。

メンバ関数は2つ。
前者は、現在のインスタンスのみ変更を掛ける関数です。
後者はこのインスタンスが使っているマテリアル全体を変更します。

NGUIが有料プラグインのため、さすがにサンプルファイルは出せません。
なので画面で使った感じを少々。

これがアトラスのインスペクタ。見えているのは数字の0です。
これが上記クラスを貼りつけた状態です。
メンバで指定した名前がそのまま適用されます。
やってるのはこんな感じ。
コインの枚数をインスタンス別に変更するため、2桁の数値をアトラスで出してます。
このようにバッチレンダリングされるアトラスは高速化に欠かせません。
今回の例はコインの親子関係まるごとCG屋さんに作ってもらった場合の例です。
他にも応用は様々に効くのではないでしょうか。


0 件のコメント:

コメントを投稿