Monthly Archives: 12月 2014

[お知らせ] サーバお引越し完了

年末に予定していたサーバのお引越しが完了いたしました。
今までは自宅サーバにてWebサイトを運用していましたが、今後のアクセス数増大に備え、AWSにお引越ししました。

自宅サーバの時はサーバのスペックの関係上表示がもっさりしていましたが、AWSに切り替えてからは比較的スムーズに表示できるようになりました。
WebサーバをApacheからnginxに切り替えたことも影響していると思います。
サイトの構成自体は全く変わっていませんので、リンクを張り直したりする必要はありません。

いよいよ2014年も終わりということで、来年はもっとサイトのコンテンツを充実させていきたいと思ってます。
今年の3月よりこのブログを開始し、色々なことを学べた1年間となりました。
来年こそはこれを土台に花開かせる1年にしたいです。

まずは制作中のゲームを完成させてサイトに公開していくことに注力したいと思います。
来年もfrom the voidとしての活動を継続して参りますので、何卒よろしくお願いいたします。

それでは、良いお年をお迎えください。

[Unity] ヒエラルキー上のGameObjectのソート

ヒエラルキー上に存在するGameObjectをソートする方法のメモ書きです。
これを行うことで、名前順や座標順などさまざまな条件でGameObjectをソートできるようになります。

■方針
GameObjectの順序を指定するメソッドTransform.SetSiblingIndex()を用いることで実現できます。
一つ前の記事に簡単な使い方を書いたので必要ならご一読ください。

このメソッドは処理を返した時点で順序が反映されてしまうので、ソートを行うには一工夫必要です。
今回は、ひとつ下の階層のGameObjectを自力で取得→テンポラリのリストに格納→これに対してソート→ソート結果をTransform.SetSiblingIndex()で反映するというやり方で実現します。

■スクリプト
以下スクリプトをソートしたい対象のオブジェクトにアタッチします。

今回は名前順でソートするようにしました。
もし、座標順など異なる条件でソートしたい場合は★マーク直下の行を修正してください。

試しに以下ヒエラルキー上の「Stage」にアタッチしてみます。

gameobjsort1

アタッチしたら「Sort Game Object(Script)」のコンテキストメニューから「Sort game object」を選択してソートを実施します。
例では以下のようになります。

gameobjsort2

「Stage」配下のGameObjectが名前順でソートされていることが確認できます。
エディタ拡張にGameObjectソートの機能を持たせられればヒエラルキーの整理がスムーズになるかもしれませんね。

[Unity] ヒエラルキーのGameObjectの順序をスクリプトから取得・操作する

ヒエラルキーに表示されるGameObjectの並び順を取得したり操作したりする方法の紹介です。

同じ階層のGameObjectは順番も保存されるようになっており、次回シーンを開き直したときも順番が変わることはありません。

obj-order

GameObjectの同階層における順序はTransform.GetSiblingIndex()で取得できます。
戻り値は0から始まるインデックスです。

実際の使い方は以下の通りです。

IndexTest.cs

上記スクリプトを試しにParentという名前のGameObjectにアタッチし、コンテキストメニューから「Show game object」を選択するとコンソール上に以下のような出力結果が表示されます。

getindex1

ObjA~Cの順序をヒエラルキー上で変更して再表示してみると、

getindex2

対応したインデックスに変わっていることが確認できます。

この順序はスクリプトから指定することも出来ます。
Transform.SetSiblingIndex()を使います。
引数には変更後のインデックスを0始まりで指定します。

先ほどのスクリプトIndexTest.csを以下のように変更してコンテキストメニューから「Shuffle game object」を選択すると、GameObjectの順序が変わります。
(Shuffleと書いてますが、厳密なShuffleではありません)

setindex

Transform.SetSiblingIndex()を実行した時点で順序が反映されるので注意が必要です。
たとえば同階層のGameObjectを座標やDepth順でソートしたい場合などに活用できるでしょう。

■参考サイト
Unity – Scripting API: Transform.GetSiblingIndex
Unity – Scripting API: Transform.SetSiblingIndex

[お知らせ] 今年度の活動

今年も残すところ僅かとなりました。
from the voidとしての今年の予定を記しておきます。

 ・サーバお引越し
 ・Departure from the Voidの移植作業

上記のとおりです。
サーバのお引越しは今週末を予定しています。
AWSを使う予定ですが、どのプランにするかはまだ決まっていません。
お引越ししてから様子見して、その後プランを変更するかもしれません。

Departure from the Voidの移植作業はあまり進んでおらず、ステージ1の序盤の敵を配置したくらいです。
動画にアップできるレベルにすら到達していません。
未だゲームを動かす土台となるシステム設計であれこれ悩んでいる状況です。

そんなこんなで色々と苦戦しておりますが、ちょっとした気晴らし程度に以下のようなゲームを作りかけていました。

giveup

クリスマスに期間限定で公開しようとしていたミニゲームです。
「サンタクローストチキン」という名前のゲームです。
サンタクロースが子供たちにローストチキンをプレゼントとして配るストーリーのアクションパズルゲームというコンセプトで制作していました。

しかし、結局のところゲームシステムの仕様をどうするかさえ、はっきり決まらないまま終わりました。
今年のクリスマスには当然間に合わなかったため、来年のクリスマスへの持ち越しとなりました。

クリスマスなのに残念な話ばかりになってしまいましたが、今回の失敗から得られたものもあります。
スケジュール管理の仕方とか、アクションゲームの作り方とか、素材の効率的な使い方とか・・・
今後のゲーム制作においてはどれもプラスになることなので、これを機によりよい制作に励んでいきたいと思います。

まずは今年のやることに専念します。

[Unity] InputManagerの設定情報をスクリプトから参照する

UnityのInputManagerの設定情報をスクリプトから参照する方法のご紹介です。
キー割り当ての変更等、既存のInput機能を拡張したい場合などでお役に立てるかと思います。

■実装方針
InputManagerの設定情報はメニューの「Edit」→「Project Settings」→「Input」から閲覧・編集できます。

inputmanager-config

しかし、これらの設定情報を実行時に取得する手段は(通常では)ありません。
そこで、エディタ拡張を用いて上記設定情報を実行時に取得できる形にします。
InputManagerの設定情報が更新されるたびに、設定情報を定義するスクリプトを動的生成すれば実現できます。

スマートな方法ではないかもしれませんが、今回はこれで難を凌ぎます。

■スクリプト
下記スクリプトをAssets配下の適当な場所にインポートします。

InputManagerGenerator.cs

これで、InputManagerの設定情報を変更してシーンを保存するとInputManager.csがAssetsフォルダ配下に作成されます。
動的生成された設定情報には以下のようにスクリプトから参照できます。

inputmanagercs-result

設定情報の動的生成はスクリプトから力技で行っていますが、導入そのものはスクリプトファイルをひとつプロジェクトに追加するだけなので簡単かと思います。
今回紹介した内容を元に、後日ゲームパッドのキー割り当ての変更方法について紹介できれば・・・と考えています。

■参考サイト
Manipulating the Input Manager in Script

[お知らせ] サーバのお引越しについて

年末も残すところ僅かとなりました。
当ブログは自宅サーバにて運用中ですが、今後のアクセス数増大に備えてサーバをAWSのクラウドサーバに切り替える予定です。
どのプランにするかは未定です。

お引越しは年末を予定しており、半日程度のサーバメンテナンスが入ります。
この間は当ブログ含め、Webサイトのページに一切アクセスできなくなりますのでご了承ください。

サーバのお引越しに伴うコンテンツやURLの変更は特にありませんので、今まで通りアクセスが可能です。
公開中のゲームもプレイ可能です。
場合によってはページの表示時間が遅くなったりすることがあるかもしれません。

ご不便をおかけしますが、何卒宜しくお願いいたします。

[Unity] キーコンフィグの実装

ゲームでキーコンフィグを実装する方法の紹介です。
これが実現できれば、ユーザの設定により自由なキー割り当てを設定できるようになります。

今回は簡易的に実装してみます。

KeyConfig.cs

動的なキー割り当てはDictionaryにより実現できます。
そして、各種キー状態取得メソッドを実装しておけば簡単に利用できます。

実際の使い方の例です。

KeyConfigTest.cs

使い方はInput.GetKey~メソッドと一緒です。
上記の例はDictionaryのキーをstring型としていますが、ここは整数型でも列挙子型でも構いません。

非常に簡単に実現できますが、キーボード・マウス入力しか受け付けないというデメリットもあります。
ゲームパッドのボタンやスティックの入力を受け付けることは出来ません。

ゲームパッドの入力状態を取得するにはUnityのInputManagerにて設定を行い、Input.GetButton~、Input.GetAxis~メソッドを用いることにより行います。
ただし、これらのキー割り当ては実行時には変更できず、参照することも出来ません。

これらのキーコンフィグを実装する方法は次回にご紹介したいと思います。

[Unity] JSON形式のテキストを扱う

サーバと通信したり外部Assetを使ったりするときに、たびたびJSON形式のデータを扱うことがありました。

Unityで簡単にJSONを扱えるパーサとしてminiJSONがあります。
スクリプトファイル一つ追加するだけで使用できるようになります。

■導入
miniJSONは下記GitHubにて公開されています。

https://gist.github.com/darktable/1411710

URLにアクセスしたら、右側にある「Download Gist」ボタンをクリックしてZIPファイルをダウンロードしてください。
ダウンロードしたZIPファイルを解凍し、フォルダを開くとminiJSON.csファイルが一つだけ存在します。

これをUnityプロジェクトにインポートして準備完了です。

■使ってみる
JSONをデシリアライズ/シリアライズするだけの簡単なスクリプトです。

minijson-test

MiniJSON.Json.Deserialize()でJsonテキストをデシリアライズします。
デシリアライズしたデータはDictionaryとして返却されるため、Dictionaryにキャストします。
後は普通にKeyを添字としてアクセスできます。

シリアライズにはMiniJSON.Json.Serialize()を用います。
Dictionaryデータ引数に渡せばJson形式のテキストがstringとして返却されます。

駆け足の説明になってしまいましたが、手軽に扱えるものとしてご紹介させていただきました。

■参考サイト
[Unity][MiniJSON]JSONデータを読み込む | CHO DESIGN LAB
UnityでJSONをあつかう – MiniJSON – Neareal

[Unity] NTPにより同期した日時を管理する

オンラインゲームなどでサーバ側と通信する際、日時管理が必要になったりします。
クライアントで設定されている日時(DateTime.Now)は各端末によって少しずれていたり不正目的で意図的に変更されたりする可能性があるため、信頼すべきではありません。
サーバと同期した日時を各クライアント端末で扱えるようにしたほうが望ましいです。

今回はUnityで開発するゲームアプリ内部でサーバと同期した日時を管理する方法を考えてみました。

■実装方針
サーバとの時刻同期にはNTPが一般的に用いられています。
サーバ側で設定されている時刻を通信遅延を考慮してクライアント側で取得できます。
この仕組みを用いてNTPで同期した時刻をゲームアプリ内部で保持するようにします。

NTPはTCPではなくUDPを使用するため、ゲームアプリ側からUDP接続する必要があります。
しかし、UnityにはUDPでパケット通信するAPIが(私が調査した限り)見当たらなかったため、.NET Frameworkのソケット通信を使って実現します。

ソケット通信の初期化は以下のようになります。

そして、RFC-2030にしたがってリクエストデータをUdpClient.Send()でNTPサーバに送信します。

NTPサーバはご自身の環境に合わせてください。
リクエストの送信に成功するとサーバからタイムスタンプが格納されたレスポンスが返ってきます。
UdpClient.Receive()でレスポンスデータを受け取ります。

しかし、上記の処理には問題があります。
Send()やReceive()の通信処理は同期で行われるため、通信完了するまで処理が返ってこないことです。
フレーム処理内でこれをやってしまうとゲームアプリが一時的にフリーズしてしまいます。

したがって、非同期で行うようするのが望ましいでしょう。
UdpClientクラスにSendAsync()やReceiveAsync()等の非同期メソッドが用意されています。
しかし、これらは別スレッドで処理が行われるのでスレッドセーフを意識しなければなりません。

結果として、マルチスレッドを用いて通信する方法がUnityのフォーラムに書かれていたのでこちらを参考にさせていただきました。

■スクリプト
起動時にNTPでサーバ時刻を取得し、1秒毎に同期した時刻をログに出力するスクリプトです。

Start()内の初期化処理にてNTPのリクエストを送信して日時を受け取る処理を別スレッドで実行します。

そして、コルーチンで通信が完了するまで待機し、正常な日時を取得できたらバイナリ形式のタイムスタンプをDateTime型に変換して保存します。

タイムスタンプは8バイトのバイナリデータで1900年1月1日を基準に何秒経過したかを表す値となっています。
上位32ビットは秒、下位32ビットは秒の小数点部分です。(固定小数点)
ビッグエンディアンで格納されているので注意が必要です。

ここで取得した日時はあくまでも同期時の日時なので、後でサーバと同期した日時を知りたい場合は同期時からの経過時間を加算する必要があります。
UnityのTime.realtimeSinceStartupはゲーム起動時からの経過時間で且つ時間操作できないのでこれを用います。

スクリプトを実行すると以下のようにクライアントの設定日時によらない日時が取得できます。

unity-ntp

流れは以上です。

今回のソケット通信を用いた方法はiPhoneやAndroidの端末では正しく実行できるかどうか分かりません。
これについては機会が出来たら確認したいです。

■参考サイト
Unity – Unity Manual
RFC-2030 日本語訳
NonSoft – NTPサーバの現在日時をシステム時計に設定するサンプル(C#.NET)
How can I receive UDP packets into Unity Webplayer? – Unity Answers

[Unity] ネットワークの接続状態を取得する

ネットワーク通信を行うゲームにて、ネットワーク接続状態を調べる方法の紹介です。

iPhoneやAndroid端末など電波状況によって圏外になったり、ユーザから機内モードに設定されたりする可能性があります。
ここでネットワークの接続状態をチェックしておけば状態に応じた処理が可能です。

接続状態はApplication.internetReachabilityから取得できます。

値は以下の通り。

NotReachable
 ネットワークには到達不可
ReachableViaCarrierDataNetwork
 キャリアデータネットワーク経由で到達可能
ReachableViaLocalAreaNetwork
 Wifiまたはケーブル経由で到達可能

実際の使い方は以下のようになります。

マウスの左ボタンが押下されるたびにネットワークの接続状態をコンソールに出力するスクリプトです。

スマートフォンの場合、キャリアかWifiのどちらで接続されているかが分かるため、巨大なデータをダウンロードするときにキャリア接続なら警告メッセージを表示するといった使い方が可能です。