Unity でのゲーム開発について検索すると色々と方法は出てきますが、どれがベストなのか? どれが古い話なのか?がわからないものです。

特に Unity5 においてはパーソナル版(DL無料)とプロフェッショナル版(75ドル〜/月)では色々と違う所もあり、尚のことかと思います。 そこで、私が個人的に Unity5 で 2D ゲームを作った際のノウハウを色々とまとめて一挙公開します! (※ Unity5 の話、それ以前の話、2D とは無関係な話が入り混じっておりますがご了承下さいませ)

前提として、Unity に標準で用意されているクラスなどはある程度知っている事とします。 わからないクラスとかが出てきたら都度 Unity マニュアル などで調べながら読んで頂ければと思います。


Sprite アニメーションの動的生成

Unity で Sprite アニメーションを実装しようと思えば、大きく分けて2つ方法があります。

  • SpriteRenderer に直接表示したい Sprite を指定し、自作スクリプトの力技で解決する方法
  • AnimatorController , Animator , AnimationClip などの Unity が用意したアニメーション機能を使った方法

前者は特別な知識が必要で、かつ Unity を利用しているメリットもなく、生産性はあまり良くないと思います。私は後者での方法を使う事にしたのですが、そこで困ったのがよくある 2D の RPG キャラクターの歩行グラフィックを 100 体作りたい場合に、 100 個の AnimationController が必要で、4 方向の歩行と 4 方向の停止の AnimationClip が必要なので 800 個の AnimationClip が必要となりました。

これはとてもじゃないが手動で作るのは苦しい。。。なんとかして、 AnimationController を動的に作ったりする方法はないのか?

「unity sprite アニメーション 動的」などで検索するも、みんな同じ所で挫折を味わっている様子でした。

結論から言うとこれはおそらく無理かと思われます。 なぜかというと、そもそも Sprite アニメーションの AnimationClip を作るには UnityEditor パッケージに含まれているクラスを使う必要があり、例えば ObjectReferenceKeyframe などが必要となります。 Unity 上では UnityEditor パッケージが使えるので、Unity のプレイボタンでテストプレイを行うだけであれば Sprite アニメーションの AnimationClip の動的生成も可能。 ですが、いざ Build を行う際には UnityEditor パッケージは Build の対象外となるため Build が出来ないという結果で終わってしまいます。

よって、AnimationClip は先に必要個数作成しておき、AnimatorOverrideController で AnimationClip だけ差し替えるのが妥当かと思います。 尚、AnimationClip を先に 1000 個作るのはしんどいだろ!という話になりますが、そこは (参考リンク:複数枚の Sprite から AnimationClip を生成する Editor 拡張コード)

エディターで作るのではなく、上記のような方法でコード上で AnimationClip を作成する方法がありますので、 こういった方法で大量生産するのが良いかと思います。(私はそういったやり方でコーディング 1 時間程度で 800 個作成しました)


ローカライズについて

私は基本無料でなんとかならないかなぁ〜と考えているので、下記のアセットを使いました。 SmartLocalization [無料]

使い方についてはサンプルを見て頂ければ十分理解できるかと思います。 ただ、付属されている LocalizedText コンポーネントについての説明がどこにもないような? これが何気に便利で、Text にこのコンポーネントを追加し、Key を指定してあげると、プレイ時に動的に設定された言語のテキストに切り替えてくれます。 なので、言語設定が切り替わったか?などのリスナーを自分で定義してあげたりなどする必要なくお手軽にローカライズ処理が完了となります。

ただ、テキストに 「現在 99 ポイント!」とか数字部分が切り替わるような表示を一つの TextAsset で表現したい場合は、 LocalizedText では対応出来ないので、別途対応が必要になります。


遷移先の Scene にパラメータを渡したい

Android でいう Intent のような事が出来ないかなぁと思っていたのですが、現状は用意されていない様子。 iOS なら ViewController に直接渡せるのですがそれも出来そうにない。 これはどうやらシングルトンを使った方法がメジャーなようです。

以下、例

using UnityEngine;
using  System.Collections;
using  System.Collections.Generic;

public class IntentManager {

    private static IntentManager instance;

    private IntentManager () { // Private Constructor
        Debug.Log("Create IntentManager instance.");
    }

    public static IntentManager Instance {
        get {
            if( instance == null ) instance = new IntentManager();
            return instance;
        }
    }

    public Dictionary<string,object> Intent;
}
int hogeId = 12345;

// 値を渡す側
IntentManager.Instance.Intent = new Dictionary<string,object>() {
    {"EXTRA_KEY_HOGE_ID",hogeId}
};

// 値を受け取る側
var hogeId = (int) IntentManager.Instance.Intent["EXTRA_KEY_HOGE_ID"];

可変長のダイアログのような表示

検索して出てくるのは意外にも Unity ContentSizeFitter コンポーネントの使い方例 にあるように、Text の中に背景となる Object を配置し、Canvas コンポーネントで描画順を逆にした例がヒットします。 ただこのやり方を使うと、Text の中に Button を配置して〜とやった場合にタッチイベントが取れない様子? (そもそも Text にも Canvas をセットしてあげないと描画順が逆にならなかったが・・・)

GraphicsRaycaster コンポーネントを個別に設定すればそこらも解決出来るんだろうけど、もっとシンプルなのはそもそも描画順をいじるために Canvas コンポーネントの追加なんてしない方法だよなぁと思っていたら、

公式リファレンスに答えがあったというオチでした。 コンテンツのサイズに合わせた UI 要素を作る uGUI からなのかな?このやり方がたぶん今後の常識になるんでしょう!

これで超簡単に Dialog を実装できそうですね!


データ永続化

知ってる②!PlayerPrefs を使うのが超簡単!というのはまぁいいのですが、これが噂によると超遅いらしい。そもそもこれは Android でいう SharedPreference を使った話なので、大量のデータ保存に特化したものではありません。Windows に限って言うのであればレジストリへの保存ですので文字数制限も気になる所。 とある方の調査によりますと、300 件以上の書き込みは秒速 6.25 個程度しか保存出来なかったそうです。 つまり、某パズルゲームのように何百体も仲間がいて、ステージクリア時に

  • 連れて行った 5 体のキャラに経験値を追加する処理
  • 所持金を追加する処理
  • スコアを保存する処理
など、PlayerPrefs に何かしら情報を書きこむ処理が複数回発生すれば、その処理に 1 秒かかるという事。 とてもじゃないが同期処理で行う訳にはいきません。 又、Android の SharedPreference はアプリ起動時に全データをメモリーに展開しますので、大量のデータがあればその分メモリーを圧迫しますので、やはり音量調整や言語設定などの値ぐらいの保存程度に抑えるのが良いんじゃないかと思います。

単刀直入に言いますと、個別に JSON 形式や CSV 形式でファイル保存するのが良いんじゃないかと (あるいは SQLite など)

Application.persistentDataPath が永続化したいファイル保存場所を提供してくれますので、 後は Jsonfx や SimpleJson などで JSON 形式でデータを保存するのが楽で良いかなと思います。 ちなみに PlayerPrefs もこの永続化のやり方も、ライトハックで書き換えが可能ですので、必要があれば復号化出来る形での暗号化処理があれば尚良いんじゃないかと思いますよ!

GoodLuck.