真夏のインディ・キャンペーン第3弾から便利だったアセット紹介

真夏のインディ・キャンペーン第3弾から便利だったアセット紹介

Unity Asset Storeでは、8月末まで 真夏のインディ・キャンペーン第3弾として40% OFFのセールを実施しています。

アセットストアで購入したものは、ほとんどがそのまま商用利用可なので細かい権利関係を気にしなくて良いのでとても気が楽です。
また、購入方法もクレジットカードがあれば簡単です。

現在制作中のゲームで利用した中で良かったものを紹介します。

iOS / Android 向けに、広告あり無料ゲームでこういうの一人で作ってます。

FEEL

FEELは、Corgi Engineの会社が出している演出・端末振動などを簡単に再生できるアセットです。
個人的に結構好きなアセットで、いくつかの機能をフィードバックとしてまとめて扱うことができます。

中には3つの機能が含まれます

  • MMFeedbacks
    • パーティクル・アニメーション・移動・拡縮・回転・サウンド・端末振動などを
      一つの演出としてまとめて再生できるコンポーネント
    • いくつも演出を作っておき、MM_Player.PlayFeedbacks()関数を呼び出して使っています。
  • NiceVibrations
    • 端末振動を制御するコンポーネント
    • この機能を使って、床との衝突時にバイブレーションを再生しています。
  • MMTools
    • ゲームビューのスクリーンショットとるデバッグ機能とかいろいろ
    • この中に含まれる MMSoundManager を使ってサウンドの管理を行いました。

上記の回転アクションは、アニメではなく回転・拡縮を組み合わせで作っています。
設定項目はこんな感じ

必要ならコレにパーティクル再生、サウンド再生、マテリアル操作による発行、端末振動も追加できます。

実際はプログラムからは直接呼び出さずに UnityEvent を使うようにし、
インスペクター上で実行しています。

こんな感じにしておくと、PlayFeedbacks()で演出を再生しつつ他のことも自由に設定や調整ができます。

using UnityEngine;
using UnityEngine.Events;

public class Animal : MonoBehaviour
{
	[SerializeField] UnityEvent m_OnJumpMissed;
	
	void Failed() {
		m_OnJumpMissed?.Invoke();
	}
}

あとからプレイヤーキャラと、フィールド用や敵用の演出を同時に再生するように変更も簡単なので直接 MM_Player.PlayFeedbacks() を呼ばないほうがいいなと思っています。
UnityEventはボタンコンポーネントの設定と同じなのでうまく使うと便利です。

注意点

FEELは、便利なアセットですが実は同社が出している、Corgi EngineTopDown Engineに含まれています。

すでに、これらを持ってる人は重複購入しないように注意しましょう。
将来的に2Dアクションとか、トップダウンアクションゲーム作りたいならもう少し出してコーギーエンジンやトップダウンエンジンを買ってしまいましょう

Nice Vibrationsについて

バイブレーション機能では有名なアセットですが、歴史的経緯でいろいろ変わっています。
古い情報を検索して混乱しないようにしましょう。

  • Nice Vibrationsとして More Mountains社が開発
  • MMFeedbacksとセットにして FEELというパッケージ化 (More Mountains社)
  • Nice Vibrationsの開発が Lofelt社 に移行
    • Lofelt Studioという振動オーサリングツールに対応
  • Lofelt Studioのサービス停止 ← いまここ
    • Nice Vibrationsがオープンソース化準備中
      • Nice Vibrationsの単体アセットは販売終了
    • Lofelt Studioがなくなったのでしばらくの間音声から波形を自動生成できなくなった。
    • ただ、Androidのことを考えるとプリセット振動を使ったほうがマシなことが多いので
      あんまり気にしなくてOK
    • 引き続きFEELには含まれる。
    • 詳細はこちら

ということで、端末振動やNice Vibrations は今後もいろいろありそうな気がします。

Easy Save – The Complete Save & Load Tool for Unity

Easy Saveは簡単にセーブデータを保存できる定番アセットです。

スクリプト的には、ES3.Load() と ES3.Save() だけわかっていればOK

// セーブデータの key からデータを読み出す。keyがなければ default_valueを返す
T ES3.Load<T>(string key, T dafault_value)

// セーブデータの key へ value を保存する
void ES3.Save<T>(string key, T value)

保存先は、ユニティエディタメニューの Tools -> Easy Save 3 -> Settings から設定できます。

セキュリティを超重要視しないない + 大容量の保存しないならほぼデフォルトでOK

暗号化はとりあえずAESにしておけばOK

Player Prefs削除ツール

Player Prefsを全消しするメニューもわかりやすいところに追加されるので便利です。

Tools -> Easy Save 3 -> Clear PlayerPrefs を押すだけです。

セーブデータを扱うクラスの例

プログラムの各所で ES3.Load() / ES3.Save()を書くと煩雑になったりキーの管理がやりにくくなるので、ユーティリティクラスを作って運用してます。

namespace App.SaveData
{
    public class SavedValue<T>
    {
        public string Key
        {
            get => m_key;
        }

        public T Value
        {
            get
            {
                return ES3.Load(Key, m_default_value);
            }
            set
            {
                ES3.Save(Key, value);
            }
        }

        public SavedValue(string key, T default_value = default(T))
        {
            m_key = key;
            m_default_value = default_value;
        }

        string m_key;
        T m_default_value;
    }
}

keyを保持しておき、値(T型)としてdefault_valueと同じ型を扱うクラスです。
下記のように使います。

// int型のレベルを定義。レベルは1から始まる
SavedValue<int> Level = new("PlayerLevel", 1);

// レベル参照
Debug.Log($"Lv{Level.Value}");

// レベル更新
Level.Value += 1;

これを PlayerData クラスにまとめておき、それを操作するようにしました。

using App.SaveData;

namespace App
{
    public class PlayerData : MonoBehaviour
    {
        public SavedValue<float> BestScore = new("BestScore");

        public SavedValue<int> CoinNum = new("CoinNum", 0);

        public SavedValue<int> PowerLevel = new("PowerLevel", 1);
        public SavedValue<int> JumpLevel = new("JumpLevel", 1);
        public SavedValue<int> EnergyLevel = new("EnergyLevel", 1);


        public SavedValue<float> LastScore = new("LastScore");
        public SavedValue<bool> UpgradeUnlock = new("UpgradeUnlock", false);

        public SavedValue<bool> TutorialLaunch = new("TutorialLaunch", false);
        public SavedValue<bool> TutorialJump = new("TutorialJump", false);
    }
}

実際には PlayerDataクラスはシングルトンだったり、DIコンテナで注入したりするといいです。

Doozy UI Manager

Doozy UI Managerは、UI表示をノードベースでグラフィカルに管理ができるアセットです。

ノードベースで管理

この例では、ResultOpen というシグナルを受け取ったら
Potalから UI Resultへ遷移し、Result UIを表示します。

Result UIの中にある ResultClose ボタンが押されたら、
Result UIを閉じてからSignalノードへ移動し、App / Retryシグナルを発行します。

実際の処理としてはアプリ側のメイン処理スクリプトがシグナルを受け取りリトライ関数を実行します。

Signal Sender / Listener

シグナルの送信 / 受信はUI管理以外にも使えます。

上は受信用コンポーネントで、 App > Retry というシグナルを受信したら、
Event() に積んである UnityEvent が実行されます。

これをうまく使うとPrefab間の参照などを断ち切ることができます。

PrefabAにあるボタンを押したときに、 PrefabB にある Player.Jump() 関数を実行する場合、
PrefabA.Button →PrefabB.Player.Jump() という参照が発生してしまいます。
この参照はPrefabAに保存できないため、シーン衝突の原因となり得ます。

シグナルを使って、PrefabA.Button を押したら Jumpシグナル発行。
PrefabB.Playerでは、Jumpシグナルを受信したら Jump() を実行。
とすると、すべてがPrefab内に収まりシーンに参照情報が残りません。

ポップアップダイアログ

よくあるこういうポップアップダイアログも自前でやると面倒なことが多いのですが、
このアセットを使うと面倒なことは全部やってくれます。

必要に応じてPrefabをInstantiate()して、指定タグのCanvasに置いてくれます。
もちろん、必要なら下の画面への入力を全部ブロックします。

Doozy UI Managerは他にもやれることが多いので、自分も少しずつ使っていこうを思います。

まとめ

FEEL、Easy Save、Doozy UI Managerを紹介しました。

この中ではFEELが一番オススメです。
Corgi EngineやTop Down Engineにも付属していますので、買うときは注意してください。