FreelyApps

個人によるアプリ開発の日記です。アプリの収入だけで生活できるようになるのが目標です。UnityでAndroid向けのゲームアプリを作成しています。


    アプリ『トランプ・7並べ』を公開しました。
    Android/iOS https://goo.gl/zsFces

    2016年01月

      このエントリーをはてなブックマークに追加 Clip to Evernote
    結構前の話ですが、5.2以降でも通じる話なので書いておこうと思います。

    Unity5.1においてUnity AnalyticsがUnity内部に組み込まれました。これによりアセットストアからSDKを落としてきて組み込むといった手間はなくなり、使いやすくなりました。Project IDというものをWebサイトから取得し、PlayerSettingsで設定するという方法でUnity Analyticsが有効になったと思います。(この記事を見ると、現在は5.1のProject IDはあまり推奨されていないみたいです。またしても5.1ではSDK方式でも対応できるようになっています。)

    Unity5.2以降もUnity AnalyticsがUnity内部に組み込まれているため、SDKは不要です。サービスウィンドウができたため、ここでUnity Analyticsの有効にすることができます。サービスウィンドウに色々なサービスがまとめられたため、やり方が変わったのが5.2です。つまり、使い方が変わっただけで5.1から進歩していません。(内部的には変わっているかもしれませんが……)

    サービスウィンドウを開くと下のようになっています。Unityアカウントにログインしないと何もできないということです。
    sw-start

    ログインすると、新しくProject IDを作るか既にあるIDをリンクするかを選ぶことができます。既にProject IDがあるというのは、古いバージョンのUnityでAnalyticsを使っていたとか、管理サイト上でProject IDを取得したということが考えられます。そのような場合はそのIDを設定すれば良いです。
    sw-start-after-login
     
    Project IDも新しく作る場合(新しいプロジェクトならそのはず)はUnityアカウントの所属する組織を選びます。Select organizationにリストが出るので、適当なものを選びます。そうするとCreateボタンが押せるようになるので押してください。
     
    新しくProject IDが生成され、ウィンドウにProduct Nameが表示されるようになりました。Analytics以外のサービスも設定できますが、今回はAnalyticsのボタンを押して有効にします。
    sw-projectid-created
     
    後は画面に沿ってEnable Analyticsボタンを押すか右上の有効・無効切り替えのトグルを押します。有効化するときに年齢制限の確認が聞かれます。(これはアメリカの法律でCOPPAというものに対応するためのものです。13歳未満の子供の個人情報を収集する際に制限があります。13歳未満対象かどうかをUnityが知るためアプリごととに設定することを求められているのでしょう。)詳細についてはここを見ると良いです。

    以上で設定は終了です。サービスウィンドウ上でもAnalyticsがONになっていることを確認できます。
    この設定が終わったら一度はEditor上で起動しておいてください。これによりPCから管理サイトにAnalyticsの情報を送ります。管理サイト上にValidateチェック用のページがあるので、それを見るとすぐに正しく接続できたかがわかるようになっています。ここらへんは以前と同じです。
    カスタムイベントの集積には最長6時間程度かかるそうなので、6時間待ってからチェックすれば良いです。


    最後に注意点を書いておきます。かなり重要なので、覚えておくとたぶん役に立つでしょう。

    Analytics.CustomEventメソッドはUnity Analyticsが有効にされていないと、「The name `Analytics' does not exist in the current context」というエラーが発生します。
    カスタムイベントのメソッドがエラーを起こすため、自分でカスタムイベントをラップして呼び出しておくのがお勧めです。

    Unityを閉じると、サービスウィンドウで設定したはずのProject IDのリンクが解除されています。内部的にはProjectSettings.assetにProject IDが保存されているためリンクされていますが、ウィンドウ上では新たにはじめる状態が表示されていてIDがなくなってしまったのかと勘違いします。
    ここでCreateしてしまうと新たにIDが増えていくので、「I already have a Unity Project ID」 を選んでリンクするのが通常の使い方だと思います。設定を変えなければ開くことはないかもしれませんが、これは結構驚く挙動です。

      このエントリーをはてなブックマークに追加 Clip to Evernote
    開発中のアプリの紹介動画を作ってみました。
    ゲスイットというトランプゲームはマイナーなゲームだと思います。そんなわけでどういう風にゲームが進んでいくのかイメージしにくいでしょう。現時点で完成している対戦画面を動画にしたので、興味ある方はどういうゲームなのか見てください。

    YouTubeとニコニコ動画にアップした紹介動画を載せておきます。内容は同じですので、お好きな方をどうぞ。




    作っていると何百回も対戦することになるので、私は感覚がマヒしてきています。面白いかどうかはもはや判断しにくいので、細かいところの作り込みをして仕上げているところです。
    AIが学習するというのが挑戦的な今作なのですが、AIの学習方法がばれるとひっかけることができてしまいます。ルールに基づいて判断する固定的なAIの方がやはり良いのではないかと思う最近ですが、学習型のAIと固定的なAIの組み合わせが最適なのかもしれないとも思っています。

      このエントリーをはてなブックマークに追加 Clip to Evernote
    折れ線グラフを描くための調査」でどうやって線を描くかを検討しました。複数のLineRendererを使って描くのが良さそうだったので、それを簡単に行うためのスクリプトを書きました。スクリーン座標のリストを渡すと、それらの点をつないだ線を描くという機能のものです。 

    機能自体はCameraとLayerを使うと簡単に作れます。このカメラは線を表示するために用意するものであり、メインカメラとは別のものを使います。
    スクリーン座標ではどこに線を描けばいいのかわからないので、CameraコンポーネントのScreenToWorldPointを使ってワールド座標で言うとどこなのかを求めます。このワールド座標を両端の位置とするLineRendererを用意すれば、線を表示する用のカメラのスクリーン上で正しい位置に表示されます。
    graph-scene
    LineRendererは1つにゲームオブジェクトに1つしかつけられないので、上の画像だと3つのゲームオブジェクトが使われています。

    当然、このままだとメインカメラや他のカメラからもLineRendererが見れます。そのためLineRendererが付いているゲームオブジェクトのレイヤーを適当なものに変え、CameraのCullingMaskを設定して線を表示するためのカメラのみが線を見れる状態にて余計に見えないように対処します。(レイヤーを使う方が完璧ですが、カメラの位置をx=10000とかで被らないようにできればそれでも同じ効果があります。)

    ここまでで折れ線グラフを描くことは達成できました。

    これをUnity UIで使いやすくするため、グラフを表示しているカメラの描画先をRenderTextureにしてみました。 RenderTextureはカメラにくっつけて使う特殊なテクスチャです。このテクスチャにカメラは描画結果を書きこむようになり、画面には表示をしなくなります。(内部的には出力先をレンダリング用のバッファから、レンダーテクスチャ用に確保した領域に切り替えているだけだと思います。レンダ―テクスチャがヒエラルキーに存在せず設定値を持つだけのものだということからもそう思います。)

    graph-rt
    RenderTexureに折れ線グラフを書き込んだ結果です。一度書いたら特に更新する必要はないので、描画用のカメラやLineRendererは破棄しても大丈夫かもしれません。

    これで単なるテクスチャとして使うことができます。Textureクラスなので、Spriteとしては扱いません。Unity UIで使うにはRawImageコンポーネントで表示すれば可能です。
    下のグラフの表示は灰色の下地の上に青色で表示しただけのものです。テクスチャになっていれば簡単にUIに組み込めるので、非常に使い勝手が良いです。
    graph-log

    メモリとパフォーマンスがちょっと心配です。パフォーマンスはグラフを動的に変化させるつもりがないので、レンダ―テクスチャに描画をし終えたらゲームオブジェクトを消して改善できそうです。メモリがどれくらい使われるかは良くわからないですが、解像度を下げるとかピクセルあたりのバイト数を減らすしかないでしょうね。

      このエントリーをはてなブックマークに追加 Clip to Evernote
    ゲームなどのアプリでは、SNS系のアプリ(Twitter、LINE、Facebookなど)に拡散できる仕組みを入れるのが常識になっています。文字だけの投稿もありますが、画像があった方が良いので最近は画像付きの投稿が行えるものも多くなっています。

    画像付きのツイートを送信するには当然画像がなければなりません。この画像はスクリーンショットを使うことがほとんどでしょう。画面を撮影した画像を特定のフォルダに保存して、その場所と文字列(アプリの紹介文だったり、ゲームの結果だったり)をTwitterアプリに渡すことで画像の付きのツイートができるわけです。
    画像を作ったり、Twitterアプリに適切なものを渡して連携するところもそれなりに難しいのですが、一度できてしまえばどんなアプリでも同じ仕組みで動きます。ちゃんと作るという条件付きですが、成功したら正しく動くのでわけのわからない問題は起きないでしょう。

    きちんと作って画像付きのツイートを送信することができたとしても、Android6.0では動かなくなることがあると判明しました。Android6.0に対応するように作っていないのだから、それはそうだという話ではありますが、Unityを使っているとAndroidを直接いじるのは面倒極まりないのです。なので対処法を見つけることにして、なんとかお茶を濁そうと考えています。

    原因はAndroid6.0以上のOSを使っている場合、権限の管理ができるようになったためでした。この権限のうちWRITE_EXTERNAL_STORAGEというファイルの保存に関わる許可を得られないと画像ファイルにアクセスできないため、画像付きのツイートができないのです。しかもTwitterが落ちることも結構あります。
    SS_TwitterAbort

    5.9以前ではアプリをインストールするときに必要な権限は全て許可するようになっていたので、開発者はAndroidManifestに必要なパーミッションを入れておけばそれで十分でした。
    しかしながら6.0ではユーザーが自由に権限をON/OFFできるようになってるため、それだと不十分なことがあります。「Android 6.0 以降のアプリの権限の管理」として公式ページで説明してあります。

    どのような操作をすると画像付きのツイートを送信できるようになるか
    をメモしておきます。Android6.0以前の端末ではきちんと動くのに6.0では動かないという場合、以下の対応で正常に動く可能性があります。(試した端末のAndroidバージョンは6.0.1でした。)
    まず画像付きのツイートをすると画像にアクセスできずにTwitterアプリが停止するといった症状が出る場合、設定->アプリを開き、Twitterにデータを渡している問題のアプリを開きます。アプリの情報が下のように表示されているはずです。
    許可というところをみると「権限が付与されていません」と出ています。この状態だと駄目なので、許可というところをタップして設定を変えます。許可をタップすると右のようにアプリの権限の一覧画面になります。ここではストレージという権限があり、それが無効になっているという状態です。
    SS_TN_PicTwi1 SS_TN_PicTwi2

    ストレージをタップして権限を有効化します。右の方にトグルが移動し、緑色になりました。これで権限がゆうこうになります。1つ前のアプリ情報の画面に戻ると、許可にストレージが現れています。
    SS_TN_PicTwi3 SS_TN_PicTwi4

    権限の有効・無効を設定した場合、一度アプリを終了させないと反映されないようです。意外と重要なことですが、忘れがちなことなので注意するべきです。


    Android6.0以降に対応したアプリでは権限の管理についても対応するというのが正しいあり方です。
    対応方法は開発者用の情報に載っています。当然AndroidのAPIを直接呼び出しています。
    権限があるか常にチェックするためのメソッドがあり、それにより権限が与えられているかを判定してプログラミングすれば良さそうです。また権限を要求するためのダイアログを出す機能も用意されていました。(Runtime Permissonとかで検索するとそれなりにヒットするので興味がある場合は調べてみるのもいいと思います。)

    端末ごとの対応はしたくないので、テキストだけのツイートにするかアプリの紹介ページに「Android6.0をお使いの方は~」 的な対処方法を書いておくのが現実的かなあというところです。
    アプリが落ちたりしないようなので、まあ妥協点です。 

      このエントリーをはてなブックマークに追加 Clip to Evernote
    ゲームをした日ごとのデータを保存して、どのように変化しているかを表示しようと思っています。最終的にはグラフで勝率を出したいのですが、データの蓄積部分が必要です。

    日付と保存したいデータの組み合わせをクラスにして、それをリストで持てばやりたいことは可能そうでした。日ごとのデータクラスをDaily、それを保持するリストを持つクラスをLogとして話を続けましょう。
    Dailyクラスは日付として、年、月、日の3つを持っていても良いし、DateTime構造体を持っていても良いです。DateTime構造体は日付の計算を楽にしてくれるので、計算のために使います。年、月、日の3つのパラメータからDateTime構造体が作れるので、どちらで保持しても情報は同じです。Dailyクラスは例えばスコアといったゲームの情報も持たせます。この情報は1日ごとに集計するものになります。
    Logクラスの中にいくつものDailyが保持されているわけですが、日が進むにつれてDailyクラスは増えていきます。ゲームの開始からずっと保持していくとどれだけのデータが必要が決められないので、日数を区切って保存することにします。例えば30日分とかです。このように決めると、リストの要素は30が限界になります。 セーブする領域も30個のDailyクラスを保持できるようにしておけばいいです。(要素数が確定すると配列でも良いような気はします。Listを使う方が便利なので、Listを想定していますけど。)

    日が進むと要らないDailyデータがリストに現れます。それは現在時刻から判断して、30日以前のものはいらないということです。
    保持しているリストにあるDailyデータの日付と現在の日付の差をとって、何日間の差があるか調べればいいです。DateTime構造体同士の差を取ると、TimeSpan構造という間隔を表す構造体が得られます。この構造体はDaysで何日間の差があるか取得できるのでこれを使います。0であれば今日であり、正であれば未来になり、負の場合は過去です。今日を含めた過去30日分のデータを取るなら、0から-29までのデータを残します。
    このようにして必要な期間のデータをリストに残すことができます。このリストの更新は今日のデータがあるかLogクラスに問い合わせて、新しく今日のデータを追加するときにリストの更新をすると効率的だと思います。

    時間をごまかすチートの対策は記録程度では要らないですが、必要であればセーブに最終更新した日付を残しておけば良いです。この最終更新日時は常に過去であるはずなので、もし現在日時が最終更新日時よりも過去であったらチートしているということになります。
    サーバーとか外部のものが使えるのであれば、そこの時刻と端末の時刻が正しいかを判定すれば良いでしょう。何かセーブするときに時刻を調べておかしくないか判定すれば、不正はできないと思います。

      このエントリーをはてなブックマークに追加 Clip to Evernote
    ゲームの日々の記録などを折れ線グラフで表示したいと思いました。それで色々調べているのですが、結構大がかりな感じでした。

    スクリーン上にUnityで線を引く方法は意外と面倒臭いようです。スクリーンの位置を渡して線を描くような関数が用意されていないからです。
    uGUIを使って細い四角形を用いてもグラフは描けるし、LineRendererGLを使っても線が描けるようです。

    UI上に線を描くようにすると、UI以外では使えません。Imageに四角を描くようにしていくつも使って折れ線を表現することができます。可能ですが、元々UIをそういった目的に使うものではないのでいまいちです。
    GLは線を描くことが関数で行いやすく簡単でしたが、特定のカメラ上でのみ描画するといったことができません。GLを使うとワールド空間内に線を直接作るようなことになります。(表示位置などを思い通りにいじるためにはCGの描画における行列の知識が必要です。Unityを使って楽にゲームを作るということからは逸脱します。GLが低レベルのグラフィックスライブラリということなので、難しくなるため初心者向けではないです。)
    下の図はGLの説明のところにあったExampleClassを適当なゲームオブジェクトにアタッチして表示してみたものです。ゲームオブジェクトの座標位置を中心に放射状に線を描くというサンプルです。
    GLExample

    線を引くならやはりLineRendererが良い感じでした。LineRendererは3D空間に線を引く機能なのですが、2Dにも使おうと思えば使えます。(2D特化のLineRendererが欲しいところです。)
    なのでこれを使って線を描くようにしていきます。LineRendererは線を四角形のポリゴンで作られているようで、ねじれたり線の太さが均一にならないことがグラフを描く上では欠点です。ねじれと太さが均一でないことをなくすには1つのLineRendererで折れ線を描くのではなく、2つの点の間ごとにLineRendererを使い線分の集合で折れ線を書けば解決できます。これによって今度は線のつなぎ目に長方形同士の重なりが起こり、きれいにつながらなくなります。単一のLineRendererはポリゴンがつながっているためにそういったことは起きないのです。

    下は1つのLineRendererで3つの点を持つ折れ線を描いたものです。折れ曲がっているところがあるため、太さが均一でないのが見てとれます。
    lr3points

    下は2つのLineRendererで3つの点を持つ折れ線を描いたものです。n点の場合は(n-1)個の線分で構成されるため(n-1)個のLineRendererが必要です。太さは均一になりましたが、線同士がつながっているところできれいに表示できません。
    2lrs3points

    グラフでは線が上に表示したよりもずっと細くします。細くなった時どちらのやり方の方が良いかというと後者の方が良いです。細くなっていくと、つながっている部分も小さくなり見えにくくなるため不自然な重なりがわかりにくいのです。線が均一でないのは細くなっても結構わかります。線同士の違いが比較できるため細くなっても問題になります。
    折れ線グラフを作るには複数のLineRendererを使って行うのが良さそうです。

    Unityでグラフを作ることを調べると有料のアセットがあることもわかったのですが、アプリで儲けるということを考えると有料だと二の足を踏みます。
    ただお金で解決できることはお金で解決するのが最も良いのは間違いないです。
    私の場合は自分で試してみるということも目的であるので、自分でできそうなら自分でやります。

      このエントリーをはてなブックマークに追加 Clip to Evernote
    PlayerPrefsを使うとセーブが作れます。当然プラットフォームによらないので、一度コードを書けばAndroid/iOSはもちろんPC上でもセーブがされています。私はWindowsで開発をしているので今日はその問題について書こうと思います。

    セーブがどこに保存されているかというとWindowsではレジストリになります。レジストリはプログラムが設定情報などを書き込むデータの保存場所です。PlayerPrefsを使うと、このレジストリにセーブが保存されるというのはあまり良くありません。データの保存場所なのだからそこに保存することは自然に見えるのですが、大きな問題はセーブ内容を直接見れることと、編集できてしまうことです。特に編集できてしまうのが悪影響を与えます。範囲外のデータが保存されるとプログラムがおかしくなるというのはよくあることです。
    開発中はセーブを自由にいじりやすいというのはメリットなのですが、配布するゲームのセーブがいじれてしまうのはまずいです。Unityを使ってPCゲームを一般に配布するなら、セーブ方法は自前でファイルに保存するように実装しないと駄目でしょう。

    Androidとかだともう少しセーブがいじりづらい仕組みのようなので、気にしないで使うことにしています。とはいえ気になる人は自分でファイルを作ってデータを保存するのが良いのは間違いないです。セーブの改ざんをどこまで防ぎたいかにもよって手間の掛け方が違うということです。

    Windowsでセーブ内容を見るにはregedit.exeを使います。これはレジストリエディタというものでWindowsに付属しています。名前の通り簡単にレジストリがいじれます。 プログラムを検索すれば見つかるので、regeditで検索して開いてみてください。
    PlayerPrefsの解説ページにあるようにHKCU\Software\[company name]\[product name]キーのところに保存されています。このキーはレジストリエディタの左側のフォルダみたいなものです。HKCUというのが略でHKEY_CURRENT_USERのキーを表しています。
    下の図だとcompany nameがFreelyAppsでproduct nameがFreelyAppsキーの下にいくつか並んでいます。当然これはPlayer Settingsの値によって決まっています。プロジェクトごとにproduct nameが違えばちゃんと区別されているでしょう。
    playerprefs-reg
    名前と書いてあるものがPlayerPrefsのkeyに対応し、データが保存されている値になります。このデータを編集するとセーブを編集することが可能です。また項目を削除すればセーブからデータの一部がなくなったことになります。

    プロジェクトに対応するキーを削除するとセーブがなくなるので、いちからゲームを始めた状態を作りたいときはそうすると便利かもしれません。
    ただキーが削除できない場合があります。先ほどの画像のトランプ・ナポレオンというキーの下の謎の文字列はそういったキーです。選択すると下のようなエラーが発生します。もちろんキーを消すこともできません。
    regedit_nullerror

    この原因はキーにnull文字が含まれている場合だそうで、キーが文字化けしているのでわかりやすいエラーです。null文字ってC言語のやつと同じなのかとかなんで発生するのかはよくわかりませんでしたが、RegDelNullというマイクロソフトによるこの問題の対応ソフトがあるので使うと削除できます。regeditにこの機能を入れておいてよとか思いつつ、ダウンロードして実行してみました。

    exec-regdelnull
    こんな風に-sをつけておくとHKCU/Software/FreelyAppsキーの下を再帰的に検索してnull文字を検知してくれます。見つけると消すか聞いてくるのでYes答えましょう。これでレジストリエディタで消せなかった文字化けしているキーを消すことができます。

    たぶん日本語名のアプリだから起こる問題なのだと思います。英語のタイトルのアプリでは起きてないと思うので、その可能性が高いです。

    レジストリをいじるときは注意しましょう。
    最悪パソコンが起動しなくなる恐れがあります。 

      このエントリーをはてなブックマークに追加 Clip to Evernote
    新しいアプリの作成状況は中心となる遊びの部分がほぼ完成といったところです。

    tg1-1
    こんな風に13枚のカードを使って2人で対戦する画面を作ってみました。手前が自分なので、カードが表になって見えています。置く側の裏向きのカードは相手の手札を表しています。これは見れません。

    tg1-2 tg1-3
    対戦が始まると相手の手札を探るために質問をし合っていきます。最終的に真ん中にあるカードを当てればいいのですが、上のスクリーンショットではかなり序盤に解答をされています。ふつうは3回程度質問してから解答することになるでしょう。

    大体のところが完成したと言っても完成度で言えば70%くらいでしょう。細かなところや使いやすさを向上させていくのは進みが遅くなっていくので先はそれなりに長いです。
    ゲームの流れがちょっとわかりにくいみたいなので、実機でのプレイ動画を作っているところです。そのうちアップして紹介しておきたいと思います。

    最後に予約トップ10というサイトで事前予約を受け付け中です。リリース後すぐ遊びたい方は予約すると良いかもしれません。
    ルールは単純なので暇つぶしにも良いですし、AIが学習していくところをみて楽しむのもおもしろいと思います。

      このエントリーをはてなブックマークに追加 Clip to Evernote
    エイジングテストとは(発音的な問題でエージングとも呼ばれます)長時間製品を稼働させて動作に問題がないかをテストするものです。工業製品などでは耐久性を見るために行われていていたりします。

    ゲームの場合でもエイジングテストがあります。これは長時間ゲームを動かしっぱなしにして問題が起きないかを調べます。ある画面で何時間も放置するとゲームが停止するといったことが起きないか調べたり、自動でゲームを進行させるようにしてエラーが起きないかをチェックします。
    エイジングでは特に後者の自動でゲームプレイを行わせ、バグがないかの検査に使うことが役に立ちます。放っておくだけでゲームをPCが自動で遊んでくれると、自分で何回もテストするよりも何倍も効率的にテストが可能です。人間がやると飽きてしまうのでどうしてもテストの精度は悪くなっていきます。これが機械にやらせれば延々と正確にテストを繰り返してくれます。
    テスト結果を見るためにログに出力するようにしたり、ゲームの進行具合を確認すると良いです。 

    エイジングを行うためにはプログラムにそれ用のコードが必要になります。ただしこれらのコードは製品には不要なので、定義があるかないかでコードを抹消できるようにしておくのが重要です。ユーザーの入力が必要な時にプログラムで模倣するようにすれば良いのです。模倣といっても人間らしくする必要性はありません。可能な選択肢の中からランダムで選択するようにしておけば十分です。選択肢が多いならまだ行っていない選択を優先して選ぶというようにするのも有効です。要は可能な組み合わせを全て行えればテストとして十分なわけです。ランダムの場合は数を増やせば自動的に全ての可能性をテストできるため、意外と良い方法です。

    人間の入力がなくてもゲームが動くようになればテストが開始できます。 この時点でエイジングテストが可能な段階になりますが、いろいろな省略を実装するとより効率的にテストが行えます。動作のバグを見つけるといったときは演出関連の処理を省いたりすると短い時間でチェックが増やせます。

    以下の例はアニメーションを最低限にしているチェックです。 高速に対戦が行われているのが見て取れます。このテストではトランプゲームのルールが正しく作れているかと、AIが学習して強くなるかを試しています。
    対戦結果のUIの表示が一瞬されるため視覚的にもゲームの進行が行われているかなんとなく把握できます。

    エイジングテストは放っておいてもずっとテストをし続けてくれるということ重要です。ゲームを起動したままにしておくことができないといけないのですが、Unityのエディターは他のアプリを選択しているときには動作を停止してしまいます。つまりエイジングテスト中はUnity以外のプログラムをPCで操作することができなくなるのです。
    エイジングテスト中にはPCで他のことをしたかったりするので、これは困ったと思っていました。
    Unityのエディターを他のアプリを選択しているときでも動作しておく方法が、ハルシオンシステムの気ままBlog「【Unity】Unityが非アクティブでも動作を進めさせておく。 」にあったので試してみました。結果は期待通り、他のアプリケーションを操作しながら、Unityエディターを動かすことができました。

    Player SettingsのRun In Backgroundをチェックすればいいのですが、このチェック項目はPCやWeb Playerなどの共有設定です。Androidにはこの設定はないので、ビルドターゲットがAndroidでもいいのかと思っていましたが普通に裏で動いてくれました。本来このプロパティは実行プログラムが一時停止されないための設定だと思いますが、エディターの動作もこれで設定されているようでした。
    ps-rib

    実はこの記事を書いているときもエイジングテストを行いながらでした。何回も繰り返すとログにもエラーが出なくなり、それなりの品質になると思います。

      このエントリーをはてなブックマークに追加 Clip to Evernote
    ゲームは一般的にセーブが存在します。セーブとは何らかの方法でメモリにある情報を保存する仕組みです。
    プログラムはメモリの情報を見て動作するので、通常は前回の実行には全く関係なく実行されます。プログラムの実行を終えたら、メモリの情報は破棄されます。メモリから情報が消されるので、再開とかは不可能なわけです。電源を落としたら最初から遊ぶようなゲームはごく普通のことなのです。

    そうはいっても今のゲームは続きから遊べるようになっています。以前遊んだステージをクリアしていたり、取得したアイテムを持っていたりするのが普通です。これは前回までのことが記憶されているということです。
    メモリに保存ができないなら、どこか別のところに保存すればいいということでセーブというものがあるのです。セーブにメモリのデータをしまっておいて、次のときにセーブからデータを読み込んでメモリ上に復元します。そうすると以前の続きから遊べるようになります。

    セーブの仕組みは端末によります。PCで言えばテキストファイルかバイナリファイルを実行ファイルのあるフォルダに作るとかになります。
    このデータをセーブ(データ)とも呼んだりするので、セーブが機能を表しているのか実体としての保存されているデータ形式を表しているのかを気をつけなくてはいけません。
    セーブデータを作る機能は扱う端末によりわかれます。ファイルの読み書きなどはOSに依存する低レベルの処理なので、かなり面倒なものです。このあたりは取り扱いが非常に面倒でありゲーム内容に依存しにくいことなので、ゲームエンジンには端末ごとの処理を書かずに何らかのAPIを呼び出すだけでセーブができるようになっています。 

    UnityではPlayerPrefsという関数でセーブが作れます。 
    PlayerPrefs.GetIntとPlayerPrefs.SetIntがセットであり、GetIntでセーブからの取得を行いSetIntでセーブへの書き込みを行います。(SetIntは厳密には書き込みではなく、書き込みのときの値を設定しているものです。しかし書き込みと考えていても基本的には問題ありません。)
    PlayerPrefsはキーバリュー型の保存方法であり、簡単に使うことができます。キーは文字列でGetInt、SetIntで同じ文字列を使うことでキーに対応する値(バリュー)を読み書きできます。
    別の値を表すのにも関わらずキーが同じものを用いてしまうと、値が上書きされます。エラーが発生することはないようです。SetFloatやSetStringで同じキーを用いても問題なく動作し、最後に呼ばれたものだけがセーブに残るみたいです。

    PlayerPrefs.SetInt("test", 100);
    PlayerPrefs.SetFloat("test", 0.5f);
    PlayerPrefs.SetString("test", "hello");
    というように同じキーで3回セットを呼んでいますが、3つ目のみがセーブされます。この後にPlayerPrefs.GetInt("test")を呼んでも、デフォルト値の0が返り100が返ることはありません。保存する型が異なってもそれらはキーによってしか区別されないということに注意が要ります。
    PlayerPrefsを使う時に最も重要なのは、意図せずキーを重複させないということにつきます。実はセーブにデータ(キーとバリューのペア)が存在してなかったみたいなことが起きても、PlayerPrefsのGet系の関数はデフォルト値を返すためにバグに気付きづらいのです。デフォルト値をいじれるので、明らかな無効値を返すようにしてしまうとかがバグを防ぐ唯一の方法な気がします。その方法も無効値が存在しないデータだと検出できないです。名前の通りキーの取り扱いにはご注意をということなら、良いネーミングセンスです。

    PlayerPrefsを直接呼び出すことで非常に簡単にセーブ機能が作れますが、セーブが大きくなってくると管理クラスなどを作った方が良いでしょう。

    オートセーブを使うゲームの増加によりユーザーにはその存在がわかりにくくなっていますが、 開発者にはセーブの存在は大きいままです。セーブに関する話題は結構あって、正解ってなんだろうかと考えさせられます。

    このページのトップヘ