FreelyApps

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


    アプリ『トランプ・ジン・ラミー』を公開しました。
    Android/iOS https://goo.gl/PYKFYG

    タグ:自動化

      このエントリーをはてなブックマークに追加 Clip to Evernote
    MonoBehaviourを継承したゲームオブジェクトにアタッチできるスクリプト(C#)を作るとします。通常はヒエラルキーにゲームオブジェクトを用意してそこにスクリプトをドラッグアンドドロップしてアタッチします。
    この作業はドラッグに失敗したりすると、非常にイライラします。
    いくつかのスクリプトをつけるときはコンポーネントの追加ボタンを押せばいいのですが、新たにゲームオブジェクトを作るときはゲームオブジェクトを作り、そこにアタッチするというちょっと面倒な手順があります。

    以前スクリプトをヒエラルキーにドラッグしたら、それがアタッチされたゲームオブジェクトを作成するようなことを試していました。
    スクリプトをヒエラルキーにドラッグアンドドロップしてゲームオブジェクトが作られるようにする」 という記事にこれが書いてあります。大体やりたいことはできていたのですが、ドラッグしたままにすると問題があったりしました。(理解して使うなら十分使えるというくらいの出来でした。)

    これをショートカットキーでやれば良いのではないかと思いつきました。 
    こんな感じに改造しました。スクリプトを見つけるところはSelectionに任せ、作るかどうかの決定はメニューを押すことになりました。
    イベントを確実に取ることが簡単なので、この方法が一番良い気がします。 

    使い方は簡単でアタッチできるスクリプトを選択した状態でCtrl+Gを押すかコンテキストメニューのCreate->GameObject from Scriptを押すと、選択されているスクリプトがアタッチされたゲームオブジェクトをヒエラルキーに作成します。
    CreateGameObjectFromScript

    複数のスクリプトから同時にゲームオブジェクトが作成でき、C#のスクリプト以外を選択してあっても無視されます。

      このエントリーをはてなブックマークに追加 Clip to Evernote
    Unityで作業している時間がどれくらいなのか知るためには、ストップウォッチみたいなもので測ったり、時計を見たりすることで大体測れます。しかし、いちいちそういったことをするような習慣を身につけなければ測り忘れたりすることは起こるので面倒だと思います。

    UnityのEditor拡張で自動で作業時間を測ることができます。この拡張は他の使い方に応用できそうなので、シンプルなままでソースを載せておきます。
    使うものはEditorApplication.updateInitializeOnLoadMethodAttributeです。


    [InitializeOnLoadMethod]をメソッドにつけておくとエディターの起動時にそのメソッドが呼び出されます。そこにエディターで毎回行ってほしいことを登録することで定期的に計測結果を保存させるようにしています。
    EditorApplication.updateは秒間100回程度呼び出される処理を登録しておくために使います。起動してからの時間を測り、経過した時間分だけ足してEditorPrefsで値を保存しています。 
    EditorPrefsはPlayerPrefsのエディター版でPlayerPrefsとは異なる場所に保存されるデータです。WindowsではレジストリのHKCU\Software\Unity Technologies\UnityEditor 5.xというキーの中に保存されます。エディターのメジャーバージョンごとに共通の場所に保存しているのでプロジェクトごとに保存される場所を変えるということができないことに注意してください。

    制御用のウィンドウを作ったり、一定時間ごとに処理をするようにしたりと色々拡張の余地はあります。EditorApplication.timeSinceStartupで時間を計測しているのが悪いのか時間の計測がうまくできないことがあります。

      このエントリーをはてなブックマークに追加 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
    ヒエラルキーにスクリプトをドラッグアンドドロップしたら、そのスクリプトがアタッチされたゲームオブジェクトがヒエラルキーにできると思っていたことがありました。それはプレハブをドラッグアンドドロップするとそのコピーができることからそんな勘違いをしていたのです。
    そうなっていてほしいことがそうなっていないので、Unityを使っていて長い間不満でした。それでどうにかできないかと思っていたので、今回なんとかしてみました。スクリプトはC#のみ対象です。BooやJavaScriptの方は型の情報が取れなかったので、やめました。といってもC#がメインでしょうからあまり関係ありません。


    以上のようにMonoBehaviourを継承していようが、継承していなくても関係なくスクリプトをヒエラルキーにドラッグアンドドロップしても何も起こりません。これはUnityの通常の挙動です。
    MonoBehaviourを継承したクラスはゲームオブジェクトにアタッチできますから、MonoBehaviourを継承したクラスのスクリプトをヒエラルキーにドラッグアンドドロップしたら、新しいゲームオブジェクトをヒエラルキーに作成しそのスクリプトをアタッチするというように変更したいと思います。


    できたものの動作は以下のようになりました。
    MonoBehaviourを継承したスクリプトのみ反応して、ゲームオブジェクトが作られています。(partialを使った場合は、クラス名と一致するスクリプトのときだけ反応します。)



    これをどうやって作ったかは結構難しい話になると思います。まず参考にしたサイトがいくつかあるのでそれを挙げておきます。
    Unity5 HierarchyにC#スクリプトをドラッグ&ドロップできるようにするエディター拡張
    Create GameObjects/Components by Dragging Assets to Hierarchy/Inspector
    の2つです。特に前者の方の目的はやりたかったことそのままと言ってもいいです。じゃあわざわざ作る必要があったのかとなりますが、うまく動かなかったので自分で作ることにしました。

    以下に作ったコードを載せておきます。現在、私が使っているUnityのバージョンは5.3.1f1 Personalです。これで動くことは確認しています。使い方は、UnityのプロジェクトにEditorフォルダを作りそこにこのスクリプトDropScript.csを置けば使えます。
    ログに”DropScript AutoStart”と出れば読み込みが完了しています。

    #if~#endifの部分は手動でこの拡張機能をON/OFFするためのものです。使いたい場合は適当なdefineを入れてください。
    重要なのはリフレクションを使って型の情報を取っている部分です。(Unity4だったら、名前でAddComponentできるので、それにclassNameを渡すだけで良いです。)Types.GetTypeという部分がドキュメントには載っていないので、使い方が正しいか微妙です。
    ドラッグのイベントは何度も呼ばれてしまうので、boolフラグで一度だけ呼び出されるように対処しています。

    完成したものは十分に要件を満たしていますが、いくつかの欠点があります。もう少し改善すると注意せずに誰でも使えるものになりますが、ちょっと無理そうなのでそれはしません。
    • ヒエラルキーにゲームオブジェクトがひとつもないと反応しない
    • スクリプトをドラッグしたままヒエラルキーを横切るとゲームオブジェクトができてしまう
    • スクリプトをドラッグしてゲームオブジェクトにアタッチすると、ついでにゲームオブジェクトができてしまう
    1つ目はEditorApplication.hierarchyWindowItemOnGUIがヒエラルキーにあるゲームオブジェクトから呼ばれているようなので、他の判定方法がないと改善できません。よって、これはどうしようもないと……
    2つ目はドラッグ中にヒエラルキーのウィンドウ外に出ることをドロップと判定されているようなので、おそらくどうよもないです。
    3つ目は個人的に結構大きな問題と考えています。ドラッグでのアタッチをやめてボタンからコンポーネントをつければ競合しないですが、気をつけないと知らずに不要なものができてしまうので問題です。
    まあ何らかの方法で対応できるかもしれませんが、これを使うとこんな感じのこともできるのでこのままの方が使えると思っています。ヒエラルキーをまたぐように行ったり来たりして大量のゲームオブジェクトを作っています。


    これすごく便利だと思うので、Unityの公式の機能としていずれ追加してほしいです。

      このエントリーをはてなブックマークに追加 Clip to Evernote
    Unity Multiplayerを使ってオンラインゲームを作るといったときにはUnityを同時にいくつも起動するということがあるでしょう。複数のUnityを起動することでそれぞれが1つの端末としてデバッグすることが楽になるためです。
    作っているプロジェクトを丸ごとコピーするなどしてプロジェクトを増やすと、Unityとしてはそれらが別のプロジェクトとして認識し、同時に起動することができるようになります。
    別プロジェクトだけれども内容は一緒というのは管理しにくいので、それについてはバージョン管理ソフトを使って、複数の作業フォルダを作るというのがお勧めです。

    何度もやると、Unityを複数起動するのが面倒になってきます。
    色々な所にプロジェクトがあったりすると、いちいちウィザードから選んだり、フォルダのところに行ったりでわずらわしいです。
    ……なので、これを簡単に行う方法を私なりに実践しています。

    やり方はバッチファイルからUnityのプロジェクトを指定して同時に起動するという方法です。
    Unityはコマンドプロンプトからも起動できるので、バッチファイルで起動することができます。同時に起動するためにはstartコマンドを使う必要があります。使わないとコマンドが終わるまで次のコマンドが実行できないからです。startコマンドにより、本来終了してから次へという処理が同時に行えるようになります。

    以下のような内容のバッチファイルを作れば5つのプロジェクトが同時に開けます。プロジェクトのパスは全て異なるものにしてください。
    バッチファイルの作り方はテキストエディタに以下のコマンドをコピーして、ファイルを"ファイル名.bat"と名付ければバッチファイルになります。

    ここから
    set UNITY="C:\Program Files\Unity\Editor\Unity.exe"

    start "" %UNITY% -projectPath プロジェクトのパス1
    start "" %UNITY% -projectPath プロジェクトのパス2
    start "" %UNITY% -projectPath プロジェクトのパス3
    start "" %UNITY% -projectPath プロジェクトのパス4
    start "" %UNITY% -projectPath プロジェクトのパス5
    ここまでをコピペしてください。

    プロジェクトのパス1~5にはプロジェクトのあるパスで全て異なるように指定してください。 プロジェクトのあるパスとは、AssetsとかLibraryフォルダを含んでいるフォルダへのパスのことです。絶対パスで指定する方が問題が起こらないので、そうしてください。

    最後に起動してみたデモを載せておきます。 
    pre-nosou

    バッチファイルのアイコンが画面中央に表示されています。それをダブルクリックするとバッチファイルの内容が実行されます。ウィンドウがいくつも表示されているのでちょっとわかりづらいですが、複数のUnity起動されています。

      このエントリーをはてなブックマークに追加 Clip to Evernote
    BGM用のファイルをインポートするとデフォルトの設定がオーディオクリップに適用されます。
    audioclipsetting

    これをインスペクタ―上から手動で設定することが普通だと思いますが、数が多くなってくるといちいち設定をするのが面倒になります。手動での設定は行うことを忘れることもあります。
    これらを解決するには自動で設定を行えるようにするのが一番です。

    AssetPostprocessorというクラスを継承してクラスを作ります。AssetPostprocessorはアセットのインポートや変更時になんらかの処理を行うために使うクラスです。
    Editorフォルダの下にスクリプトをおかなければいけません。(Unity5からなのかEditorフォルダの下に置かなくても動作するようになっていました。しかしながら、互換性のためEditorフォルダに置くことを推奨します。) 

    上のスクリプトはBGMをインポートしたときにオーディオクリップの設定を行うサンプルです。
    BGM_IMPORTERシンボルが定義されていれば、Resources/Sound/BGMにおかれたオーディオクリップをストリーミング再生で圧縮フォーマットはOgg Vorbisというように設定します。
    新しくオーディオファイルを追加したときはこのスクリプトの処理が行われます。既に追加してあるファイルに処理を通したい場合は、リインポートを行うかオーディオクリップの設定を変更すると処理が通ります。
    リインポートはアセットを選択した状態でAssetsメニュー->Reimportを選択するかアセットを右クリックして出るメニューからReimportを選択すればできます。フォルダを指定するとそのフォルダ以下をリインポートすることもできます。

    上記のスクリプトはBGM用に作ったものですが、少し改造すればSEやVoiceといったBGMとは少し設定を変えるであろうオーディオクリップにも使えます。
    フォルダを分けるのが素直な方法だと思います。 Resources/Sound/SEとかResources/Sound/Voiceにあるファイルだったらで場合分けするというのがお手軽です。

    こういった自動化用のスクリプトはEditor拡張というやり方でUnityは柔軟に対応することができるようになっています。 Editor拡張は面倒なことが多いのですが、一度作ってしまうと後の作業を劇的に減らしてくれる可能性を秘めています。
    同じような作業を繰り返していると感じているときは自動化できないかと考えてみると楽ができます。

    このページのトップヘ