Google

2012年8月31日金曜日

Unityでコインゲー開発;ネイティブ拡張の実際

今回はiOS版で拡張した際の話とその詳細。

あちこちで書かれているので今更感はありますが、外部連携時の細かい話をば。
このときの要求はこんなでした。

 「公式にHTML置くんで、Unityからシームレスに表示して欲しい」

となれば、iOSならUIWebViewを使うことになります。
Safariが起動して、本体がバックタスクに回るのはNGって事ですな。
その際に行ったのは以下のような処理でした。

 ・プラグインは自前で全て実装
 ・UnityFWのUIVewの上にUIWebViewを被せる形
 ・後はURLにアクセスするだけ

そういえばUnity拡張時の基本の概念がなかったので改めて書いてみます。
Unity自身は、プロジェクト内部に包含されたソースやリソースについて、どれがどのプラットフォームで使うのか、という区別が付きません。
ファイルひとつひとつにそういった属性の情報を細かく持っている訳ではないという事です。
では何でやっているかというと、これで区別しているのです。

 「Project以下のディレクトリに付けられた名称」

単純過ぎて管理ミスがでそうな仕組みですが、昔からこうです。
で、外部連携プラグインを設置していい場所も決まっています。
iOSやAndroidの場合はここ。


Pluginsの下にiOSとAndroidがありますが、この下に各々ネイティブコードのソースを設置します。
ここまで適当にプラグイン、プラグインと言ってますが、明確に書くとUnityのプラグインとは以下のような構成になります。

 [Unity Plugin構成]
  /Assets/Plugins/
    C#/JSで書かれたstatic関数だけの集まりクラス
  /Assets/Plugins/(ネイティブOS名)
    ネイティブコードで書かれた実装処理

最低でもこの2組の構成が1つのプラグインとして動作します。
ネイティブの方は自由に書けますが、UnityFWを含んだ塊がアプリの本体で、そこに対して処理を行うとか、上にViewを被せるとかの概念を気にしなければなりません。
Unity側の方はむしろAdapterパターンとなり、Unity側との橋渡しがメインです。
そしてこのUnity側のクラスは全てコンパイル前にアドレスが決定しなくてはならず、その関係で全てstatic関数で構成する必要があります。
例えばこんな感じに書きます。


public static class iOSPlugin
{
// Safariを起動。被せるURLは決まっているので引数なし
[DllImport ("__Internal")]
public static extern void startSafari();
}


これはiOS版ですがAndroidでも原理だけは同じで全てstatic関数必須です。
初期化、実行、メモリ解放等の考慮して順序良く呼ばれることを想定した関数群にし、呼び出しもそれを守る必要があります。
あーめんどくさいですな。

ちなみにわざわざプラグインを書いてにアクセスする理由ですが、現場ではこんな裏事情がありました。
 
 ・ランキング情報を送信してユーザに見せたい
 ・コレクション実績をサーバに送信したい
 ・コイン残数を同期して不正防止したい、、、、等々

中身の処理の詳細は長くなるので今回は割愛。
しかし、サーバ連携の基本GET/POSTの仕組みはネイティブ側で行うので、Unityからは引数で渡すだけの話です。

次回はちょっとずれて、XCodeでまれに発生するプラグイン実装時エラーの回避方法を書きます。

2012年8月30日木曜日

Unityでコインゲー開発;iOS拡張をプラグインで

先日のiOSの話の続き。

Unityではできない拡張機能。
単体では実現できないので、Pluginで対処するのが普通です。
コインゲーに限った話ではないのですが、Unityで開発する際、拡張をどのように考えたかという話が今回の記事です。

まずUnity Asset Storeにはサードパーティ製のプラグインが転がってます。
これが元々Unityの売りでもあったはずなので種類も豊富です。
じゃあ実際にやるとなると、現実的な選択肢となるのは以下の2つ。

 1.頑張って勉強して自前で作成
 2.時間がなければ金で解決

1は自己責任ですが自由になのは当たり前。でも面倒。
2は使ったら時間が稼げるかもしれませんが、それはそれで問題がでます。
実際に遭遇したのはこんなケース。

 ・検索したけどニーズにあったツールが売ってない
 ・売ってたんだけど、いざ調べたらもう無くなってた
 ・プラグインの評価がみんな星ひとつ
 ・買ってみたらトラブル続出で動かない
 ・マニュアルが英語(これはほぼ100%のプラグインが英語なんで問題なし)

もう二度と買うもんか!って感じのもありましたね、、、。
まあたいていのプラグインは安いですし。会社の経費で買う分にはどうにかなりますが、動かないと最悪です。

悪かった例ばっかり書いても仕方ないので、よく使う必要があると思われるツールを1点、実際に使った現実例として紹介します。
先日は2D系を出しましたが今回は「iOS用アプリ内課金」プラグイン。
これです。


お値段は$50。
わざわざ買わなくても、StoreKit Frameworkの処理をちゃんと書けばいいと思われるかもしれません。
が、この時の担当者は私たった一人だったので、それをコーディングする時間すら惜しくて思わず買ってしまいました。

んで、結論から言うと一応アプリの購入はちゃんとできました。
時間もある程度短縮もできました。その点では成功といえます。
逆に困ったのが以下。

 1.プロダクトIDを複数入れて詳細を要求すると何も帰って来ない
    →1個入れれば大丈夫だった
 2.コールバックで結果が戻るが細かい内容が取れない
    →しょうがないのでレアケースは放置
 3.サーバトラブル時に何が戻るか分からない
    →意図的にサーバ側でエラー処理を書いて値を検証
 4.XCodeビルド時、手動でStoreKitFWとこのプラグインのLibを毎回追加
    →マニュアルを書いて明示化
 5.ARM指定を間違えるとエラーでランタイムエラーになる
    →実機ビルドで検証

このツールは実処理が*.aという拡張子のライブラリになっていて、ブラックボックスでした。
マニュアルはあるんですが、内部の処理がどうなってるのかが解りません。
特に引数指定の方法が悪いとか、癖がある関数の使い方がちょっとアレで、何度か検証が必要になったりしました。
まあ、そのへんは何度も検証を繰り返せは辿り着くんですが、4.の手順が一番面倒だった記憶があります。

Unity側でXCodeのプロジェクトを生成する際、FWは最低限必要なものだけチョイスしてしまうので、必要なものは自分で追加しなければなりません。
次のビルドからはBuild and RunでAppendオプションにすればいいんですが、間違えると全部やり直しになります。
また、このプラグインのようなネイティブライブラリ型は、XCodeのプロジェクト内部に自分で追加しなければなりません。
この場合は「libPaymentPlugin.a」というファイルでした。

けど確かこのaファイルはXCodeプロジェクトの一番上に置かないとなぜかビルドが通らなかったりとかいう現象にも遭遇した気が。


また、気づいたらプラグイン本体がバージョンアップしてたりするんですが、通知もなかったりでもう色々がいろいろです。
これらから分かるUnityの現実、それは、、、、

 「拡張機能が沢山あってもやっぱり夢の万能ツールではない」

という点ですかね。

2012年8月28日火曜日

Unityでコインゲー開発:iOS

今回はiOSとの話。
Unityって改めてざっくり言うとこんな感じです。

 ・3Dは得意
 ・2Dは苦手
 ・Unityの中だけで完結するなら幸せ
 ・ネイティブOS連携は大変というかごちゃごちゃ
 ・仕事はプラットフォームSDKでビルド可能にする所まで

普通、ゲーム本体のことだけ考えてれば終了、、、、なんて事はありません。
必ず外部との連携や面倒くさい話が出てきます。
実際に出てきたのはこんなケースでした。

 ・公式へのリンクボタンを入れたい
 ・ヘルプを内部HTMLで見たい
 ・Twitterでツイート
 ・アプリ内課金をしたい
 ・広告を入れたい(iAd, AdMob, リワード系その他)

上記はiOS版の際の話です。Androidの時はもっとややこしかった記憶が。
ほとんど埋め込みはしたのですが、とにかく面倒。

まあ、公式へのリンクなら、これ使えばいいので簡単でした。

 Application.OpenURL

ヘルプも公式リンクならいいんですが、地下鉄でどうしようとか、ビルの中でどうしようとかいう話になるわけでして。
となるとアプリにHTMLを埋め込む必要が出てきます。
しかし2D画像だとマウス操作等が色々あるのでHTMLが現実解でした。

が、これも置き場所が決まっていて、Assets/StreamingAssets/でないとダメとか、呼び方が違うとか色々ありました。

  Unity公式 StreamingAssets

上記に解説がありますが、プラットフォーム別に書き方を変更しなければなりません。
このURLにはAndroidの説明が無いのですが、参考までにAndroidならURL指定は以下のようになります。

 file:///android_asset/ファイル名

これを各Web表示のネイティブコンポーネントに渡す訳です。
マルチプラットフォームってやっぱ逆にめんどくさい。

長くなってしまったのでこの話は続きます。



2012年8月26日日曜日

Unityでコインゲー開発:TexturePacker

先日書いた2D系のツール話の続きです。

記事にて一番使いやすいと書いたNGUI。
Unityは描画コール回数の削減でテクスチャを1枚にまとめる必要があるのですが、このNGUIと非常に相性の良いツールがあります。
それが今回紹介する「TexturePacker」です。

 http://www.codeandweb.com/texturepacker

フリーでお試し可能、正式版だと2000円ぐらいとリーズナブル。
使用中の画面はこんな感じ(本家からの転載)

使い方は簡単、まとめたいjpg、pngを全部突っ込んで、オプションからUnityを選んで、生成ボタンを押すだけ。
指定場所にアトラスイメージと画像の配置情報テキストの2つが生成されます。
作成したアトラスはAtlasクラスを紐付けたGameObjectに割り当てるのですが、真骨頂はここから。


上の画像は、NGUIを使ったスプライト定義のインスペクタです。
矢印の「Atlas」の部分を見てください。
スプライトの設定部分にTexturePackerで生成した情報を突っ込むだけで、即アトラスマッピングが完了するという簡単さが売りです。
各画像の指定方法ですが、画像から拡張子を抜いたファイル名をそのまま指定する形なので管理も簡単。
NGUIとこのツール2D周りの統一・高速化・簡略化が全て行えます。

このツールのお陰でコインゲームにおける2D周りの処理はかなりコストが稼げたようなもんです。
皆さんもぜひお試しください。そもそも安いですし。

次回はiOSとの連携の話を書きます。

2012年8月24日金曜日

そういえばUnity4が

今日は余談。
Unity4使い始めました、ってブログやつぶやきで見かけるようになりました。
が、私はまだ使う気はありません。

だって毎回こんな目にあってきたから。

 ・プロジェクトがコンバートされ、古いバージョンには戻せない
 ・よく解らない現象や原因不明のエラーが出る
  (しかもいつの間にか治ったり内容変わったり)
 ・Unity自身のバグを回避したコードが無駄になる
 ・プラグインとの相性に問題が出る場合が(まれに)ある
 ・古いバージョンとの多重起動は(当然ながら)かなり難しい

開発の真っ最中にUnityバージョンアップがあった場合、人柱PCに最新版を入れて、コンバートテスト、動作テスト、ネイティブSDKとの連携テスト全て終わらせ、それから全員にVer.Up許可の通知という手順が普通でした。
アセットサーバにバージョンが違うプロジェクトをコミットされた日にゃあ、それはもう発狂もんでした、ええ。

卑怯かもしれませんが、安定してから購入する予定です。
まあ、「クライアント様の環境に合わせる」のが現実解という事でw

2012年8月23日木曜日

Unityでコインゲー開発:2Dプラグイン

更新間隔がちょっと長くなってますが続き。

Unityは今更言うまでもなく2D面が非常に弱く、皆苦労してますね。
2D処理専用のOnGUI()は先日のブログの通り、毎回コールされてしまう仕様ではとてもじゃありませんがiOSで使えません。
しかも3Dの世界をあまり理解しないお客さんに「解像度のまま綺麗に出して欲しい」とか言われるとこちらもかなり困ってしまったりします。

そんな微妙な状況の中、現場で試したプラグインはこれらです。

2DToolKit
EZGUI
NGUI
最初のやつは古すぎたせいか、元々あまり良い印象は有りませんでした。
バージョンアップは頻繁で良かったのですが、Unityエディタ上では問題なく動作し、実機で動作させた際にだけヌル参照で落ちるという、相当厳しいレアなバグに出会したため、なくなく使うのを諦めました。

それでもテクスチャを1枚のアトラスにまとめてくれる機能だけはとても使いやすかったと記憶しています。
あ、1枚にまとめる理由ですが、、、

 http://docs.unity3d.com/Documentation/Manual/DrawCallBatching.html

このへんにも書いてありますが、描画回数を減らし高速化するための策です。
スマホではこのあたりは死活問題になりますので速度で悩む前にまずドローコールを調べるというのはUnityに限らず常識ではないかと。

EzGUIはさらに印象が悪く二度と使う気にはなりませんでしたw
デモ画面に騙されたーという人も多かったかも知れません。
もう設計思想を疑うぐらいのめんどくささです。

んで、最後のNGUIが事実上の本命でした。
ヒエラルキー階層に制限があったりしましたが、Unity2Dの現実解を見せてくれたのはこのツールだけです。

実はこのNGUIは非常に相性のよいツールがあります。
安くて良いツールなのですが紹介はまた続きで。

2012年8月19日日曜日

Unityでコインゲー開発:時間短縮その3

コインゲー開発で実際に行った時間短縮の続き。

列挙体を書かない、ということを以前書いてありましたが、これについて詳しく話します。
普通開発に於いて列挙体という定義を書かない時はありません。

列挙体ってのは、簡単に言うと種類を定義することなんですが、専門外の方はわかんないですよね。
例えばUnityで使うC#でアイテム一覧なんかを書くならこう書きます。

// アイテム一覧
public enum ITEM_TYPE
{
 COIN_1,   // コイン1
 COIN_10,  // コイン10
 COIN_50,  // コイン50
 CAPSULE, // コレクションカプセル
 BOX     // ランダムボックス
};

んで、アイテム管理クラスなどで、ここに定義された列挙体を変数で持ちます。

 private ITEM_TYPE item_type;

もしくはアイテムを抽選で出す場合、確率情報から決定されたこの列挙体を元に、どのプレハブを実体化させるのか?という判断にも使います。
他にも型付けの強さを持ってコンパイルミスを防ぐとか色々あるんですが、山ほど作るこの列挙体をほとんど作りませんでした。

特にアイテム系は一切。

仕様書にはエクセルで種類全てが書かれるのが普通なんですが、この時は以下の様な仕様確定シーケンスだったのです。

  1. アイテムの系統を決める(コインとか、ランダムとか)
  2. バリエーションを決める
  3. 値段を決める

特に2の作業が開発後半までいろいろモメました。
増えたり減ったりと仕様変更があるのは世の常ですが、エンジニアの立場としては非常に嫌です。
しかも納期だけは最初から確定でしたし。orz

んで、列挙体を書かないという荒業につながるのですが、ここでやっと具体的な話をば。
Unityのインスペクタ、publicメンバにすることでで出るアレ、あれを使います。
あれを配列にすると個数と実体をUnityからぐりぐりと紐付けできるので、これを最大限に有効活用するのです。

この配列に何を登録するかというと、先日公開したInstanceManagerを行うわけです。
実際にはこんな感じ。

 public ItemInstanceManager[] m_instance_mgrs;

そしてアイテム種類別のインスタンスマネージャをn個実体として作り、ぺたぺたと紐付けます。
そして配列の添字そのものがアイテム種別として扱う、といった方法です。
拍子抜けかも知れませんがこれは結構リスキー。
しかし現場で以下のルールを決めることで、非常にうまく行きました。

 ・連番のエクセル資料だけは作る。
 ・予め入りそうな空きも考えておく。
 ・抜けは実行時に判断し、実体があるものだけを使う。
 ・アイテム追加削除作業はプランナーが行う(!)

この方法により、アイテムの種類増減がかなり自由になったのでした。

実際のサンプルが無いと解り使いかもなので、これもそのうち公開してみます。

今回はここまで。

2012年8月17日金曜日

今日は飲み会

関係ない話ですが。
今日はコインゲームを開発した仲間と打ち上げ。

 東京豚バザール
 http://r.gnavi.co.jp/g011038/

炭火で焼いてくれるおいしいお店でした。

豚中毒という商品。
BBQソース肉に、クアアイナのフライドポテト。美味。

左が東京タワーカクテル。右がスカイツリーカクテル。
氷型LEDで中から光ってます。

ふざけてLEDを混ぜてみました。紫w
今日は開発の愚痴や昔話で盛り上がりました。

2012年8月15日水曜日

Unityでコインゲー開発:時間短縮その2

残りの時間短縮について続き。

デバッグチートボタン。
これはどんなゲームでも開発中に作って当たり前です。
特に確率だけでゲームしているようなコインゲームの場合、確率当選で出るアイテムなどはテスト時間が長引くため必須です。

これらは開発当初から思いついたものをどんどん入れて行きました。
以下の様なものを入れた記憶があります。

 ・コイン残枚数のリセット
 ・全体のリセット
 ・抽選で当たる値の事前予約

こんな小ネタでさえもやらないという人が以外と多いのですが、そういう癖を付けると中期スパンでの時間に大きく影響します。

じゃあデバッグボタンをどの機能で作るかというと、UnityではGUIクラスが普通でしょうか。

 Unity API Refernce GUI.Button

上のサイトでもあるように簡単に書けるのですが、この処理は気づきにくい特性があります。それは、、、

 iOS版ではOnGUI関数が必ず毎フレーム呼び出されてしまう

という嫌な現象です。
そもそもUnityはデスクトップ上と実機では、FPS等の細かい動作が違うのが当たり前なのですが、遅めのiPhoneだとそこそこ変わってきてしまってあー面倒、って事がよくありました。
そのため、OnGUIは関数自体も含め、本番時に全て消せるようにするのが常識となっていました。

もう一つ、デバッグモードの概念も必要です。
UnityにはDevelopment Buildというモードがあり、これは「File」→「Build Settings...」から開いたダイアログでオプション設定を行えます。


 公式解説はこちら。
 Unity API Reference Debug Build

これがオンだとMonoDevelopでブレークして追えたりとか色々できるというものですが、これを判断するためのフラグが以下。

 Debug.isDebugBuild

この変数が真の時はDevelopment Buildがオンなのです。
デバッグなんだか開発ビルドなんだか間際らしいですが、どっちももともと同じような意味なのでそれは良しとして。
もっと大事なことが以下。

 Development Buildは、XCodeのデバッグビルドとはまた別物

なんだかややこしいことばかり書いてますが(汗

要は、UnityのデバッグモードはUnityのなかだけで通用する概念なのです。
Unityが吐き出したXCodeでのデバッグ、リリース、ディストリビューションはまた別の概念です。

ここを間違えるとデバッグの概念がごちゃごちゃしてきますのでご注意を。

なんか書いてて変な方向に行ってしまいましたが。
次回は「列挙体を書かない」で高速化する方法です。

2012年8月13日月曜日

Unityでコインゲー開発:開発時間短縮

今回は開発時間の話。

何件かあったUnityプロジェクトの中には、実装が私一人でやらざるを得ないという案件もありました。
4人ぐらいで作れたプロジェクトもあったんですが、1人はさすがにキツかったです。
しかもそーゆーのに限って、2ヶ月ちょいぐらいで仕上げろと要求が。orz

しかし最初から無理と言うのは至極簡単です。

ゲームの基本的な仕様書も、CG素材や音楽は別にありました。
お客さんがレベルデザイン等のバランス系もやってくれるという条件も貰いました。
それでも中身が非常に多く、不測の事態が起きた場合に保証ができないとは伝えたのです。
が、最悪延びたら掛かった分は出すという滅多に無い条件が貰えたため、とにかくチャレンジしてみる事にしたのです。


でも正攻法で作ってたら絶対に間に合いません。
Unityセミナーに行ってどうなるという話でもなかったので、海外コミュニティをあさり色々と考えた策を色々試すことにしました。
ざざっと挙げるとこんな感じです。

  1. 設計は実装しながらアジャイル風に同時進行
  2. 大筋は仕様書に沿うが、細部の仕様は任せてもらう
  3. バランス調整が絡む変数はすべてインスペクタに出し、私は触らない
  4. デバッグ用チートボタンを作る。
  5. 列挙体を作らないw

Unityに直接関係するのが3.位になってしまうのがアレですがw
一応これらの作戦を続ける事にしたわけです。

1.と2.は、取り立てて説明の必要もないかと思います。
アジャイル、と断言はできなくてもそれモドキの開発ならよくある話です。
設計を頭の中でやりながら実装っていうのも(時間に追われて)いつもやるのでこれもさほど問題にはなりませんでした。

さて、関係するのは3.です。
かなり前に以下の様な記事を書きました。

 Unityのインスペクタ

通常、privateにしてゲッタセッタをつけるのがセオリーのメンバ変数をわざわざpublicにすることで、ソースよりも変更が優先されるという危険極まりないシロモノです。
これを大量に適用し、バランス調整や確率データ、その他係数などをすべて目に見えるようにしました。
管理系はやばくなりますが、私はそれらの値を一切触らず、開発しながらゲームバランスを次々と調整してもらうという手段に出たのです。
printやDebug.Logで出すメッセージも極力インスペクタで見てもらうことになりました。

ソースの共有にはAssetServerを使ったのですが、これを仕えたからまだうまく進みましたが、でないとかなり面倒だったかもしれません。
このツールも万能ではなく、修正箇所がぶつかってしまい面倒になることも何度かはありました。
が、この方法は功を奏し、テストと仕様との相違による戻りを稼ぐことができました。


なんか長くなってしまったので残りは次回。

2012年8月11日土曜日

Unityでコインゲー開発:背景

ポリ数の話の続き。

コインは10角形あたりでどうだろうという話になりました。
次は背景、つまりコインが落ちる台などのポリ数です。

コインゲームに必要なのはまず背景うんぬんより、ゲームとして必要なコライダーです。
オーソドックスなコインゲーに必要なものはこんな感じでしょうか。

 ・コインをプッシュするプッシャーボックス
 ・プッシャーの下にある台
 ・コインが裏に飛ばないようにする壁(これもボックス)
 ・左右の下からせり上がってくる壁(これもボックス)

画面が見えなかろうが、これらの透明なコライダーさえあればゲームとしての基礎は成り立つわけです。
逆に言えば他は見た目に関する部分だけ。
コインが転がったり引っかかったりするなら複雑な形もいるんでしょうが、幸い私が担当したのはまだシンプルな方でした。

が、しかし、CG屋さんから貰った背景FBXを入れ込んでみたところこれがどっこい。
装飾が複雑で多く、さらにコライダーまで見た目に近い形でつけられており、当然ながら実機上での動作は重くなってしまったのです。

ここで普通は「もっとポリ数下げろ」だの「綺麗に出せないのか」などの嫌な雰囲気になることが多いのかもしれません。
ま、そもそもCG屋さんにちゃんと指示を出せなかった自分が悪いので、ここは個人の裁量責任で思い切った策を取ることにしました。

結論から言うと、「映画の書割でごまかしてみよう作戦」です。

コインゲームというのは斜め上から見ることが多く、カメラの動きは大した要求が来ません。
なのでカメラ角度、位置をある程度決めてしまい、コライダーに合わせた背景画像をビルボードに描き設置する、、、、という訳です。

アクロバット的なことをしているように思われるかもしれませんが、絵を書く人がむしろ曲芸って感じですかね。

というか、書割を角度込みで書ける人ってそんなにいません。

私の周りにもそんな人はいなかったので、ちょっとした小技で対処しました。
その技はといいますと、、、

 「カメラ位置角度は本番と同じにし、背景FBXを配置した状態で、SSを撮る」

という、まあ、ご想像どおりのひどいやり方です。
が、これも功を奏し、エフェクトなどに関係ない部分は実質2ポリという、負荷を稼ぎまくる結果になったのです。

さすがにせり上がる壁なんかはどうしようもないので普通にFBXを配置しましたが。
という事でステージの構成が大体固まって来たのです。

続きます。

2012年8月9日木曜日

WiMaxの1Dayでハマった件

Unityとは関係ない話ですが。

普段WM3600RとMacBookProで、Wimaxの1Day契約を使ってます。
とっても便利でいいのですが、焦っているときに限って通信契約にてこずる事があります。
大したネタではないのですが、備忘録とど忘れの反省を兼ねてメモ。

前提1:既に1Dayをベース契約完了していること。
前提2:自宅で無線LAN、出先でWimaxと切り替えて使っている。
前提3:今出先でいきなりネット通信が必要になった。公共無線も見つからない。

この状況に於ける、2回目以降の1Day契約の手順です。

1.Wimax端末の電源

 電源ボタンを長押しで入れます。

2.無線LANを有効にし、WiMax端末のアクセスポイントにつなぐ。

 初期状態から変更してなければaterm-*****といった感じのポイント名のはず。
 ポイント名称は端末裏に記載があるのでここでは戸惑いませんね。
 設定画面は「192.168.0.1」で見れますが1Dayではあまり関係ないのでパス。

3.ブラウザで契約画面を表示する。

 ここが今回のキモその1。
 よくやるのは、設定画面から1Day購入ボタンを探しまわってしまうこと。
 設定画面の中からは直接1Day購入のリンクボタンはありません。
 ではどうやるかというと、ブラウザを開いてどこでもいいからアクセスを試みればおkなのです。

画像は拾い物。こんな画面になります。
1Day支払い前だからこそ、アクセスしようとするとそこに飛ばされる訳です。
 このまま手続きに沿って進めば通常は完了。
 丸々1日、快適なブラウジングが楽しめます。

4.トラブル

 キモその2。
 1Dayの支払い手続きを行う画面は「https://payment.uqwimax.jp」です。
 ここで今回はミスりました。
 高速化のために、Macで普段Wifiでアクセスする設定を以下のようにしていたのです。


 上の図のように、固定でGoogleの高速DNSを指定してしまっていたのが運の尽き。
 設定画面には「192.168.0.1」で入れるためドメインが関係ありません。
 が、payment.uqwimax.jpが検索できず一向に進まない。
 外のアドレスを指定してもブラウザに何も出ません。
 数分ほどping打ったりしながらゴニョゴニョやって、はっと気づいてDNSのアドレスをDHCPから貰うように変更して解決しました。

解ってればなんてことは無いのですが、焦ってる時に限って忘れるというマーフィーの法則のような事をしてしまいました。

次回はUnity話に戻ります。




Unityでコインゲー開発:ポリ数

今回からまた制作話に戻ります。

今までの流れで解説したインスタンス管理システムですが、このお陰でメモリの問題はほぼ解決となりました。
初期プールのサイズによってロードやゲーム開始が遅くなるという懸念がありましたが、実際は100インスタンス程度なら問題ないことも判明し、この件は一段落となった訳です。

後々、Unityが公式に出したパフォーマンス改善方法の中に、正にこのような管理をする旨の記載があったので、正しかったことを実感することになるのでした。

続いて出てきたのは高速化におけるもう一つの基本、ポリ数です。
言うまでもなく、ゲーム中に出るモデリングのポリ数は少ない事が正義なので。

ちなみに先日のデモは、コインのコライダーは円錐です。
デモはいいのですが、製品版でこんな贅沢な判定を使っていたらCPUパワーが幾らあっても足りませぬ。
なので当然ながらコインはモデリングするという流れになりました。
その際、コインゲームとして問題となったのは、何角形にすればいいか?という点です。

スマホの無料コインゲームは全て落として検証したのですが、結論だけ言うと以下のような事が分かってきました。

 ・円錐を採用してるゲームは総じて重く、ゲームになっていない。
 ・6角形のメダルはプッシャに押されると横への移動率が多くなりすぎる。
 ・8角形は問題があるものの、遊べなくはない。

そのため、8か10か12角形のメダルで、という事で落ち着いた訳です。
(後々12角形ではなく10になるのですがそれはまた別のタイミングで)
実際、海外にはこういうコインがあったりします。
最も多く画面上に出るコインは方向が決まりました。
続いて背景のポリ数になるのですが、これもまた別の話がでてきたのです。

続きます。


2012年8月7日火曜日

Unityでコインゲー開発話:ソース解説2

昨日に引き続き、管理側のクラスの詳細解説をします。
管理側のソースはアイテム側よりやや大きめです。

using System.Collections;
public class InstanceManager : MonoBehaviour {
 public ManagedItemBase m_prefab;
 public int m_instance_count;
 private ArrayList m_item_list;
 private bool[] m_is_rental;
 private Vector3 m_standby_pos = new Vector3(0, 2, 0);
 public void rental(){
  int index = getStokIndex();
  if (-1 != index){
   GameObject obj = m_item_list[index] as GameObject;
   obj.transform.position = m_standby_pos;
   obj.rigidbody.velocity = Vector3.zero;
   obj.rigidbody.angularVelocity = Vector3.zero;
   obj.active = true;
  }
 }
 public void giveBack(ManagedItemBase item){
  m_is_rental[item.m_id] = false;
  item.gameObject.active = false;
 }
 private int getStokIndex(){
  for (int i = 0; i < m_instance_count; i ++){
   if (!m_is_rental[i]){
    m_is_rental[i] = true;
    return i;
   }
  }
  return -1;
 }
 void Start () {
  m_item_list = new ArrayList();
  m_is_rental = new bool[m_instance_count];
  Quaternion qua = new Quaternion();
  for (int i = 0; i < m_instance_count; i ++){
   GameObject obj = 
    Instantiate(
     m_prefab.gameObject,
     m_standby_pos,
     qua)
      as GameObject;
   ManagedItemBase item =
    obj.GetComponent();
   item.m_id = i;
   obj.active = false;
   m_item_list.Add(obj);
   m_is_rental[i] = false;
  }
 }
 void OnGUI () {
  if (GUI.Button(new Rect(0, 0, 100, 50), "Rental")){
   rental();
  }
 }
}

m_prefabaには事前に作成したシリンダーにManagedItemBaseを紐付け、プレハブ化したものを関連付けしておきます。
publicのm_instance_countは、実行時に作るプールの数です。
インスペクタでメモリの余裕具合に併せて数を指定しましょう。
m_item_listにはインスタンス実体が格納されます。
m_is_rental配列は、プールの貸し出し状態を真偽で記憶させて置く場所です。
m_standby_posは実体が待機する場所です。

まずはStart()でやってること。
インスタンスプールを作るため、プレハブを元にm_instance_count個分インスタンス化し、ArrayListにどんどんいれていきます。
貸し出し状態の判定配列もm_instance_count個分作成します。
生成アイテムには連番を付け、死んだ際の身元判明を明確にしておきます。
ここで重要なのがactiveフラグの値を偽にしていること。
これはGameObjectとMonBehaviourを不活性にし、シーン上の負荷等をほぼ0にしてくれます。
無効なものはactiveを偽にしておくことで軽減しているわけです。

次にOnGUI()。
これは押されたらレンタル関数を呼ぶだけなので省略。

続いてrental()。
ここで貸し出しを行います。
貸し出し配列から開いてる場所を探し、見つかったら該当するGameObjectをアクティブにします。
ここでアイテムは有効になり、指定された位置から落ちてくる訳です。
velocityとangularVelocityをゼロにしているのは、死んだ際のリジッドボディの加速情報等をそのまま記憶してしまっているのをリセットする目的があります。

次は逆のgiveBack()。
これは昨日のManagedItemBaseの位置が一定以上になった際、彼らから呼ばれます。
実戦では身元が正しいかどうかチェックすべきでしょう。
ここでactiveを偽にしているので、また次に呼ばれるまで眠りに落ちる訳です。

最後、getStokIndex()。
これは簡単で、貸し出し状態の配列を検索して開いてる場所を返すだけですね。

急ぎ足でしたが、こんなところです。
実際はこれらを拡張し、アイテム種別毎にInstanecManagerを造り、シンプルな構造を重ねあわせて使っていく形になっています。

次回からはまたコイン開発話に戻ります。

2012年8月6日月曜日

Unityでコインゲー開発話:ソース解説1

今回はデモのソースを軽く解説します。
UnityはC#とJavaScript、Booが使えますが、実務ではC#以外あまり見ません。
Jsって遊ぶにはいいんですが、現場の作業となると厳しい時があります。

ということでまずアイテムクラスから。
ManagedItemBaseクラスは全てのアイテムの基礎となるクラスです。
コインゲーは様々なアイテムがあるので、実際にはここからコインクラスに派生したりします。


まずメンバ変数から。

public static InstanceManager m_instance_mgr;

自分が落ちた際、自分自身が死んだことを通知するために必要です。
コインインスタンスは複数生成されるので、staticにして全インスタンスで共通にします。
属性がpublicなのは記載時のミスです。private等でアクセッサ設定が望ましいでしょう。

private static float m_fall_pos = -1f;

これは死んだことにするY位置で、これも全インスタンス共通です。
判定コライダーを置いて、とかやるとコインが飛び散ることを計算する必要があったので、敢えてこうしました。
一見遅そうにみえて、この方式では大した負荷にはなりません。

public int m_id;

この変数で各インスタンスにナンバリングしています。
Unity側の管理からもidが付きますが、仕組みに引っ張られると今後のVerUp等で嫌なので自前で管理しています。
が、これをなぜpublicにするのか。
C#にはアクセッサという便利な宣言方法があります。
しかしUnityではpublicの単純なメンバにするとインスペクタに表示され、実行前は永続的、実行中はその間だけ変数を修正できるという利点があります。
また、実行中にどのインスタンスがが出ているのか?という管理にも役立ちます。
けっして適当にpublicになっているわけでは有りません。

続いて関数でやっていること。

void Start()

ここではインスタンスマネージャを検索して保存しています。
最初の1個目以外は同じ処理を行いません。

void Update()

常に自分のY位置を検索しています。
実はコードからtransformを参照すると、内部でGetComponentが走るため、この処理自体は重い構造です。
早くしたければtransformを事前に参照するメンバ変数を持つと良いでしょう。
y位置が変数の値より下ならonFallを呼びます。

void onFall()

これも本来ならprivateかpublic virtualにすべきでしたね。
死んだ際の処理をここに記載します。
インスタンスマネージャに自分が死んだことを通知しています。

次回はマネージャ側を解説します。


2012年8月4日土曜日

Unityでコインゲー開発話:デモ

コインゲーム開発の続き。

今回は以前言っていたインスタンス管理のサンプルを公開します。
先日のクラス図をほぼ体現させた、必要最小限の構成になっています。

これはデモのスクリーンショットです。
実際に遊ぶには以下からどうぞ。
ブログに直接貼り付けてUnityPlayerのインストールとか出るとイヤな人が居ると思ったので別ページにしてあります。

 デモページへ移動

見れない場合、Unityをブラウザで見るためのプラグインを入れてください。
Win/Macの大抵の有名ブラウザに対応してます。

 Unity Web Playerダウンロードページへ

デモの操作は簡単、ボタンを押すとコインが落ちてきて、斜めの台を滑ってある高さまで落ちると消えます。
というか、それだけのデモです。

ま、WebPlayerだけでは何やってるか解らないので、今回は上記のプロジェクトも併せて公開します。
欲しい方は以下のアドレスからどうぞ。

Unityプロジェクトファイル(InstanceManageProject.zip/256,943byte)
SHA-1 Hash値:07D845B58612993D1EA82F3A00BBADDB5D869B40

商品にしたものはこれよりはるかに複雑ですが、基礎構造はよく似ています。
これはあくまで基本的な管理方法なので、ここから工夫して様々に修正、改良しやすくなっているかと思います。
このプロジェクト、ソースコードの著作権はANGEWORKに帰属しますが、内容自体は自由に改変・再利用して頂いて構いません。

クラス内部の詳細はまた次回紹介予定です。

2012年8月2日木曜日

Unityでコインゲー開発話:閑話休題

今日は色々忙しかったので横道にそれた話を。

コインが落ちる速度ですが、スマホアプリで色々差があると思いませんか?
A社は速いけどB社は遅いとか。

これは単に3Dエンジンの中でスケールが違うだけの事が多いようです。
Unity本家にも書いてあるんですが、積み木を崩すなら小さく、ビルを壊すなら大きく作れ、との事です。

何のことはないのですが、カメラ上は同じでも、1cmのコインが30cm落ちるのと、1mのコインが30m落ちるのでは、空気抵抗も時間も違って当然です。
で、Unityには重力係数(約9.8g)を変更する場所もあるにはあるんです。

場所は「Edit」→「Project Settings」→「Physics」からみれます。


このYの値、「-9.81」を変えれば、重力の法則も変わるという訳でして。
これをプラスにすると、X-MENのマグニートーごっこも出来たりしますw

色々試行錯誤した処、コインの直径を30cm位にすると、見た目にもゲームバランス的にもまあまあだって結論になりました。
なにより先日書いたコインを落とすだけのデモ。

サイズの比率を変えたバージョンを6つ位作ったのですが、サイズに全く関係なく負荷の上がり方がほぼ同一という事も判明した、ってこともありました。
ならばどうせ管理するんだし、最も平均的なのを、って事で決まったのがそのサイズです。

あまりにコインサイズが小さいと、あっという間に落ちてしまって詰まらない、っていう観点もありましたね。
実際ゲーセンでメダルゲームやると、メダルが落ちるのって速いですよね。
あれをまんま再現しても、真実が面白さやユーザビリティに直結するとは限らないといういい例じゃないかと思ってます。


閑話休題は終わり。
次回に続きます。

2012年8月1日水曜日

Unityでコインゲー開発話:管理クラス設計

負荷実験の続きです。

前回書いた負荷テストのデモ版ですが、実機では以下の現象が発生しました。

 コイン生成数が一定数を超えた時点で一気にCPU負荷が上がる
 deleteしたはずのコインのメモリが開放されない

デモ版では、Y座標が台座の下になったらdeleteするような仕組みを入れておいたのですが、やはりメモリが開放されないことが確証されてしまいました。
という事でやっぱり全てを管理せざるを得ないという結論になったわけです。

で、考えたインスタンス管理の構造ですが、要件はこうです。

 ・MonoBehaviour派生クラスのインスタンスプールで管理する
 ・アイテムは複数種類管理可能なように、基底アイテムクラスを準備
 ・プールの数はインスペクタで簡単に変更可能にする
 ・インスタンスにはそれぞれに連番を付ける
 ・生きてないクラスはActiveフラグで制御する
 ・セーブロードに対応可能にする

これらの概念は組み込み開発の経験が役立ちました。
組み込みは広域operator newを自力で作成する事から始まるので、こういった管理の方法はそこそこ慣れてた訳です。

構造にするとこんな感じ。


次回簡単なサンプルを準備しようかと思ってます。
この仕組は今でもUnityを使う上での正解のひとつじゃないかと思ってます。
実際この構造のお陰で速度、メモリの点で大きく恩恵を受けました。
起動スピードまで早くなって助かったのを覚えています。

続きは次回。