コスパ最高! 格安特盛エフェクトアセット!【Epic Toon FX】

対象読者

・エフェクトの使い方がわからない人
・エフェクトアセットがいろいろあって何買えばいいのかわからない人
・コストパフォーマンスが高いアセットが欲しい人

はじめに

こんにちは。Jaol-Industry の Jaol(ジャオル)です。
個人でアプリ開発をしております。

みなさん、開発順調ですか?
ゲームを構成する重要な要素の一つに「エフェクト」が存在しますが、エフェクトでお困りでしょうか?
敵に攻撃が当たったときのエフェクト、味方を回復させるエフェクト、アイテムを取得した際のエフェクトなど、エフェクトの利用箇所は枚挙に暇がありません。

私は今まで十数本のアプリを開発してきましたが、基本的にこちらのエフェクトアセットだけで事足りています。
Epic Toon FX

epic-toon-fx

こちらのアセットは 2021/8 現在 $38.5 ですがよく値下げセールをしており、直近の最安値ですと $11.55 の場合もあるようです。
ただ原価でも元は取れるぐらいの価値はあると思っています。

Epic Toon FX | Unity AssetStoreまとめ 割引情報 beta
https://assetsale.herokuapp.com/ja/contents/16995

こちらのアセットが素晴らしいのは価格が安いのもありますが、とにかくエフェクトの量が多いです。
現状300種類のエフェクト、さらに基本的に4色ほどのカラーバリエーションが用意されているのでいろんな場面で使うことができる頼もしいアセットです。

エフェクトの使い方

シューティングゲームのように、エフェクトを使って自機からレーザーショット(弾)を撃ってみましょう。
自機用に以下の無料アセットを導入し、オブジェクトを画面に配置しておいてください。
FreeSpaceShip
https://assetstore.unity.com/packages/3d/free-space-ships-37562

まずはコーディング(C#)します。
今回は簡単に自機が動き、弾を発射するだけにしましょう。
※ コードを簡略化させるために一つのクラスで記述していますが、実際は弾自体をShotクラスなど別クラスとして設計した方が拡張しやすかったり管理しやすかったりします

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

public class Ship : MonoBehaviour
{
    // 自機が動く速さ
    const float SHIP_MOVE_SPEED = 0.1f;
    // 弾の速さ
    const float SHOT_MOVE_SPEED = 0.5f;

    // 移動位置
    private Vector3 movePos;
    // 加速度
    private Vector3 acceleration;

    // 弾管理用コンテナ
    private List<GameObject> cntShot;

    // 今回の主役
    // 弾エフェクトオブジェクト
    [SerializeField] // インスペクタに表示するための魔法
    private GameObject shot;

    // Start is called before the first frame update
    void Start()
    {
        // 各種変数初期化
        movePos = new Vector3();
        acceleration = new Vector3(0, SHOT_MOVE_SPEED, 0);
        cntShot = new List<GameObject>();
    }

    // Update is called once per 100msec
    // Update は frame 毎だが FixedUpdate は 20msec 毎(Project Settings/Timeで変更可能)
    void FixedUpdate()
    {
        // 弾を動かす
        MoveShot();
        // 自機を動かす
        MoveShip();
    }

    private void MoveShot()
    {
        // コンテナ要素を順次実行するが、条件によっては削除するため逆順で実行 よくある手法
        for (int iIdx = cntShot.Count - 1; iIdx >= 0; iIdx--)
        {
            // コンテナからアイテムを取得
            GameObject tmpShot = cntShot[iIdx];

            // インスタンスが存在しないか、自機から一定距離離れていたら削除
            if ((tmpShot == null) || (GetDitanceFromShip(tmpShot.transform.localPosition) > 10f))
            {
                // オブジェクトを削除
                Destroy(tmpShot);
                // コンテンからも削除
                cntShot.RemoveAt(iIdx);
            }
            else
            {
                // 弾を移動させる
                tmpShot.transform.localPosition += acceleration;
            }
        }

        // Zキーが押されていたら弾を発射する
        if (Input.GetKey(KeyCode.Z))
        {
            // インスペクタから登録されているオブジェクトをコピーする
            GameObject tmpShot = Instantiate(shot);
            // 弾オブジェクトの初期位置を自機と合わせる
            tmpShot.transform.localPosition = this.transform.localPosition;

            // 弾オブジェクトを操作するためにコンテナに登録
            cntShot.Add(tmpShot);
        }
    }

    private void MoveShip()
    {
        // 移動位置初期化
        movePos = Vector3.zero;

        // 下記はすべて斜め入力などにも対応させるため else if ではなく if
        if (Input.GetKey(KeyCode.UpArrow))
        {
            // 上キーが入力されていれば上へ
            movePos += new Vector3(0, SHIP_MOVE_SPEED, 0);
        }
        if (Input.GetKey(KeyCode.DownArrow))
        {
            // 下キーが入力されていれば下へ
            movePos += new Vector3(0, -1 * SHIP_MOVE_SPEED, 0);
        }
        if (Input.GetKey(KeyCode.LeftArrow))
        {
            // 左キーが入力されていれば左へ
            movePos += new Vector3(-1 * SHIP_MOVE_SPEED, 0, 0);
        }
        if (Input.GetKey(KeyCode.RightArrow))
        {
            // 右キーが入力されていれば右へ
            movePos += new Vector3(1 * SHIP_MOVE_SPEED, 0, 0);
        }

        // 現在の距離に移動位置を加算
        this.transform.localPosition += movePos;

    }

    public float GetDitanceFromShip(Vector3 pos)
    {
        // 自機からどれだけ離れているかを計算
        Vector3 shipPos = this.transform.localPosition;
        float fDistance = Mathf.Sqrt(Mathf.Pow((pos.x - shipPos.x), 2) + Mathf.Pow((pos.y - shipPos.y), 2));
        return fDistance;
    }

}

上記のShipスクリプトを、配置しておいたShip_1オブジェクトに設定(アタッチ)し、インスペクターからエフェクトアセット(今回はLaserMissileBlue)を設定します。

実行すれば以下のように動く想定です。

上記のように、EpicToonFX / Prefab 配下のエフェクトアセットを設定すれば簡単にゲーム内にエフェクトを設定することができます。
詳細に記載すると長くなるので省きますが、エフェクトは基本的に ParticleSystem という機構を用いており、Playメソッドなどで任意のタイミングでエフェクトを実行することが可能です。
任意のタイミングでエフェクトを実行する場合は、インスペクタ / ParticleSystem / Play On Awake のチェックを外さないとゲーム開始時に実行されてしまうので注意してください。

使用例

実際に私がどのように本アセットを利用しているのか実例を以下に示します。
どこに使っているかはキャプションを参考にしてください。

ボタンを離した際に飛び散る火花のようなエフェクトと、明るくなった際の花火

ローディング画面のくるくる

左側敵死亡時のドクロ、右側味方レベルアップ時のキラキラ、ゲージが溜まった際の足元のエフェクト、右側のUnityStrikeの光の玉

機体のアフターバーナー マウスとの距離とアセットのscaleを変更させることで実現してます

アイテム系すべて
小惑星衝突時のバリアやダメージが多い際の火花、ゲームオーバー時の爆発

下部獲得ソウル、下部スキル選択可能エフェクト、上側合計ソウル、モブ消滅時エフェクト

アイテム生成時のキラキラ

相手をふっとばす際のエフェクト(X軸逆になってるw) アイテム強調表示の青い光

エモーションの動くサムズアップや顔

前と同様に盛り上がった場合の花火(これは失敗例だけど)

音声選択時のエフェクト、盛り上がった場合の花火

飛んでる際のキラキラ

Evacuate To Earthのシステムの流用なのでアイテムなどもほぼ一緒ですね
追加で使ったのはビームエフェクトぐらいでしょうか

最後に

アプリ開発を本格的に初めて三年ほど経ち、アセットはいくつも購入しましたが、やはりこのアセットがトップクラスにコストパフォーマンスが良いです。$50 – $80 ぐらいの価値があるぐらいに思っています。
ゲームにおいてエフェクトは派手に、わかりやすく表現するために切っても切り離せない存在なので、こちらのアセットはとてもおすすめです。

皆さんのゲーム開発が楽しく、実りあるものになることを祈っています。