【Unity】パーティクルシステムで光剣っぽいエフェクトの作成

というわけで、仕事繁忙のため全然更新できていませんが、今回のお題はこちらです!

shot2ss20161001091241801

剣のモデルから「光の剣」のようなものを出してみました!
「武器に光が纏って強くなる」なんてシチュエーションはファンタジーなゲームでよくありますよね!
プレイヤーがこの状態になると攻撃力やリーチが上がり、見た目と相まってテンションが上がったりします。

パーティクルシステムの Renderer モジュールで、生成するパーティクルの形状を変化させることができます。
初期状態では Billborad ですが、これを Mesh にしてモデルを指定すればOKです。

このあたりはテラシュールブログさんに分かりやすく記載されております。

下準備

パーティクルのベースとなる剣のモデルを作成します。
剣といっても柄の部分は不要で、刃の部分だけそれっぽくなっていればいいので、割と適当でも問題ありません。
そんなわけで、Blender でさくっと作ってみました。

shot2ss20161001100028913

今回は専用のモデルを作りましたが、キャラクターが剣を持っている場合はそのメッシュを使ってしまっても大丈夫です。
ただし剣の刃と柄が1オブジェクトに結合されている場合、パーティクルのエフェクトに柄も反映されてしまうので注意が必要です。
専用のモデルを作ると剣の形に依存しなくもなるので、モデルの状態や作成するゲームの雰囲気に合わせて・・・といった感じでしょうか。

ベースエフェクトの作成

光の剣となるエフェクトを作成します。
新規でパーティクルシステムを作成し、パラメータを設定していきます。

shot2ss20161001092021719

shot2ss20161001092101239

ポイントはやはり Renderer モジュールのメッシュ指定です。
これを剣の位置・移動に合わせるため、 剣に近い bone の子オブジェクトに設定し微調整します。

地味に詰まった点として、RenderMode を Mesh にし、シェーダーを Particle~ 系にすると、画面上に表示されなくなってしまいました。
ProjectSettings→Player→Other Settings→Auto Graphics API for Windows にチェックを入れることで解決しました。

shot2ss20161001092242887

新規プロジェクト作成時はチェックが入っているので外れている理由が分かりませんが、Windows10 にしたから・・・かも?
7→10のアップデート時にいろいろトラブったので、関係がないとは言い切れなそうです。

shot2ss20161001093940980

出来上がったのがこちら!
ちょっと安っぽい感じはしますが、雰囲気だけならそれなりに出来ているのではないでしょうか。
マテリアルの設定とかテクスチャとか拘ればもっと見た目はよくなると思われます。

20161001_01

振り回すとこんな感じに。
見た目は剣のリーチが伸びたように見えますが、現状では攻撃判定が伴っていない詐欺エフェクトだったりします。
通常時と光剣時で攻撃判定を分ける必要がありそうです。

ちなみに剣の軌跡の部分は「X-WeaponTrail」というアセットで簡単かつ綺麗に作れます。
下の記事で紹介しています。

「X-WeaponTrail」を使った武器の軌跡について

サブエフェクトの作成

↑だけでは寂しいので、何か適当にエフェクトを追加してみます。
関連オブジェクトをまとめるための空オブジェクトを作成し、先ほどのパーティクルを子オブジェクトとした上で追加していきます。

まず簡単にできるエフェクトとして、剣から少しオーラが出ているような見た目にしてみます。
メインエフェクトを複製し、Start Speed を少しだけ上げてみました。

shot2ss20161001095516161

もし「水の剣」など流動的なものを想定する場合は Start Speed ではなく、 Gravity Modifier を使うとそれっぽい見た目になります。
上げすぎると自己主張が強くなるので、少しだけ上げましょう。

shot2ss20161001100342543

あとちょっとしたエフェクトとして、剣の周りに粒子を出してみます。
今度は Shape を Mesh にして先程と同じ剣のモデル選択し、RenderMode は Billborad にします。
その他はデフォルトのマテリアルで適当に。

shot2ss20161001095638977

エフェクトとはちょっと違いますが、光剣という名目なのでライトが欲しいところです。
適当に PointLight を追加します。

shot2ss20161001095747584

上は Range が50、 Intensity を1.5に設定してあります。
Directional Light が効いていると微妙ですが、暗い場所なら目立つ・・・かも。

まとめ

そんなわけで、パーティクルシステムを使った光の剣 (っぽいもの) について考えてみました!
攻撃時の見栄えがかなりよくなるので、強力な攻撃の際には付けると良さそうです。

【開発メモ】チャージ攻撃とエフェクトの実装

というわけで、今回はボタンを押し続けて溜め、放すと攻撃する「チャージ攻撃」の実装になります!
これまたアクションゲームでは割とよくあるアクションです。

20151120_charge

現在攻撃系のボタンは「通常」と「特殊」の2つがあります。
今回実装する「通常チャージ」と「特殊チャージ」と合わせれば4パターンに分岐できます。
やや複雑ですが、幅広いアクションを持たせることができそうです。

通常チャージと特殊チャージを別々に行えるようにするか、片方のみにするかは検討中です。
変に共通化しても面倒なことになりそうなので、別々にチャージできる方がいいかなーとは思います。
ひとまず今回は通常チャージに相応する部分を作ってみました!

実装方法

PlayerクラスのUpdate()内にInput.GetButton()を入れ、攻撃ボタンが押されているか評価します。
押されている間は専用のカウントを加算します。
カウンタはAnimator.setFloat()でAnimatorに設定しておきます。

以下はPlayerクラスのUpdate()内の該当部分の処理です。

// チャージ時間をAnimatorにセット
animator.SetFloat("ChargeCount", chargeCount);
if (Input.GetButton("Attack")) {
    chargeCount++;
} else {
    // ボタンを離した場合は0に設定
    chargeCount = 0;
}

Player側で行うのはこれだけ。
アニメーションの制御はAnimatorControllerに任せてしまいます。
「パラメータが設定値を超えているか判定し、超えていたらトリガーをONにする」といった感じのスクリプトを作成します。

using UnityEngine;
using System.Collections;

namespace StateController {

    public class SwitchTriggerCondition : SwitchTriggerByKey {

        [SerializeField]
        private string conditionName;

        [SerializeField]
        private float count;

        public override void OnStateUpdate(Animator animator, AnimatorStateInfo stateInfo, int layerIndex) {
            if (switchByButtonUp) {
                if (Input.GetButtonUp(inputKey)) {
                    switchTrigger(animator);
                }
            } else {
                if (Input.GetButtonDown(inputKey)) {
                    switchTrigger(animator);
                }
            }
        }

        private void switchTrigger(Animator animator) {
            if (animator.GetFloat(conditionName) > count) {
                if (useAnimatorPlay) {
                    animator.Play(parameterName);
                }
                animator.SetTrigger(parameterName);
            }
        }
    }
}

世間一般の溜め攻撃の発動タイミングは「ボタンを離したとき」ですね。
汎用性のために「押したとき」か「離したとき」かを切り替えられるようにしておきます。

また、Animator.Play()を実行するかどうかも制御できるようにしてあります。
ステートの遷移をすぐに切り替えたい時はAnimator.Play()でやってしまうのが手っ取り早いです。

このスクリプトを「チャージ攻撃へ遷移する可能性のあるステート」に付与します。
今回は待機状態であるIdleから遷移させるようにしました。
CondtionをChargeAttackにし、ExitTimeのチェックを外しておきます。

実際のところは移動中やジャンプ中、他の攻撃中でも割り込んで遷移させたいところですが・・・該当ステート全てにスクリプトを付けていくのは面倒で、よろしくない気もします。
AnyStateから遷移させれば一撃ですが、あらゆるステートから割り込めてしまうためNG。
ここに限らずAnimatorの実装に怪しい部分が多いので、一度見直したほうがいいかもしれません。

チャージ中のエフェクト

アニメーション的には出来ましたが、現状ではチャージしているかどうかが分かりにくいです。
ロックマンシリーズのようにチャージ中のエフェクトが欲しいところです。

20151120_1

RenderModeを「Stretched Billborad」に設定し、LengthScaleを調整するとこんなエフェクトができます。
チャージ量が規定値を超えたら色合いやサイズを変化させ、フルチャージが分かるようにします。
PlayerクラスのUpdate()でチャージカウントを判定し、変化させてみました。

  
if (10 < chargeCount) {
    chargeEffectParticle.enableEmission = true;
    if (GameConstants.CHARGE_COUNT < chargeCount) {
        chargeEffectParticle.startSize = 2f;
        chargeEffectParticle.startColor = new Color(0.5f, 0.5f, 1f);
    } else {
        chargeEffectParticle.startSize = 1f;
        chargeEffectParticle.startColor = new Color(0.8f, 0.95f, 1f);
    }
} else {
    chargeEffectParticle.enableEmission = false;
}

chargeEffectParticle はParticleSystem型です。
インスペクターからパーティクルを設定しておき、Start()でGetComponentしています。
CHARGE_COUNT はひとまず60で定義してあります・・・が、短い気もするので後々変えるかもです。

まとめ

ということで、ざっくりですがチャージ攻撃を実装してみました!
チャージが必要なので連発はできませんが、その分高性能で派手な攻撃にしていきたいですね。

【開発メモ】Effekseerを使ったエフェクトの作成

というわけで、まだまだPHPな日々なりべるんです。
やっとSymfony2にも慣れてきましたが、未だに詰まる部分もあります。
EntityやType、DBとの連携など、意識すべき部分が多いです。

今回はエフェクト作成ツール「Effekseer」を使ってみました!
オープンソースのフリーソフトで、GitHub上で公開・開発されています。

エフェクト作成ツール自体は前からいろいろ探しており、有名所の「Prominence」や「SpriteStudio」は訳あって断念した経緯があります。
Effekseerはオープンソースで、かつUnityとの連携プラグインもあるとのことなので、ちょっと使ってみることにしました!
基本的に作成物も含めてフリーのようですが、使用するゲームを公開する場合はコピーライト表記が必要らしいです。

Unity標準のShurikenを使っていませんが、利便上「パーティクル」カテゴリに分類してあります。
何かしっくりこないので「エフェクト」とかに名前を変えた方がいいかも。

エフェクトの作成

所謂「ソニックブーム」のような衝撃波をEffekseerで作ってみます。
「横向きの衝撃波→横向きと縦向きの衝撃波→衝撃波の移動」のような感じになります。

sordwave

下準備として、衝撃波のテクスチャを作成します。
GIMPで適当に刃の形を作り、フィルター→変形→風で調節します。

・・・透明な背景に白いテクスチャだとさっぱり分からないですねorz
一応画像にマウスポインタを乗せるとうっすらと見えます。

shot2ss20151112215027049

Effekseerを起動し、描画共通タブから衝撃波のテクスチャを読み込みます。
ノードに対して以下のように設定しました。

【共通】
・生存時間:中心、40

【回転】
X:120、Y:270、Z:0

【拡大】
X:15、Y:15、Z:12

【描画】
・描画:スプライト
・配置:固定
・ブレンド:加算
・フェードイン:あり、フレーム数10

バージョンの違いか、画面レイアウトが若干異なっている場合があります。
自分の場合、「回転」の項目がなかったので、メニューのウィンドウから表示させました。

shot2ss20151112215452840

次に縦と横両方の衝撃波を生成するため、ノードを2つ追加します。

最初の衝撃波の生存時間が40なので、生成開始時間を40にします。
適当に回転角度を付け、縦と横で十字になるように調整。
あとは衝撃波を移動させるため、「位置」タブの速度のZを1.5に設定します。
他のパラメータは最初のものとほぼ同じです。

完成間際になって重要なお話ですが、Unityへインポートした際のXYZ軸に注意する必要があります。
Effekseerビュー上の青い線の方向が前になるように作ると上手くできます。

・・・とここまで書きましたが、正直分かりにくいと思われます!
今回のサンプルとして、以下のリンクからファイルとテクスチャをダウンロードできます。
こちらを見て頂いた方が手っ取り早い・・・かも。

サンプルダウンロード

プロジェクトを開いた際にエラーが出る場合、各ノードのテクスチャを解除→再選択すると直ると思います。

インポートと実行

Effekseer公式からUnity用プラグインをダウンロードし、Assets上にインポートします。
空のGameObjectを作成し、EffekseerEmitterを付与します。

shot2ss20151112215813049

PlayOnAwakeやLoopはUnityのパーティクルと同じですね。
EffectNameにはEffekseerからエクスポートした.efkファイルの名前を指定します。
・・・のですが、デフォルトでは「/Assets/StreamingAssets/Effekseer/」直下のディレクトリを参照しにいくようです。
StreamingAssetsなんてディレクトリは作っておらず、そもそもエフェクト系は別ディレクトリで管理しているので、そこを参照しにいくようにソースコードを修正します。
EffekseerSystemの15行目付近になります。

public static string resourcePath
{
    get {
        return Path.Combine(System.IO.Directory.GetCurrentDirectory(), "Assets\\Particle\\Effekseer");
    }
}

GetCurrentDirectory()でプロジェクトまでの絶対パスが取得できるので、あとはAssets~から先のパスを指定します。
自分は「Assets/Particle/Effekseer」にしました!
上記ディレクトリ内に.efkファイルを放り込み、再度実行してみます。

shot2ss20151112215702041

今度はしっかり再生されました!
ちょっとエフェクトを入れるだけでもかなり違うもので、前に紹介した「X-WeaponTrail」と合わせると攻撃系は別物と言えるレベルになります。

注意点として、作成時にテクスチャ等の外部ファイルを使用した場合、Effekseerのプロジェクトファイル(.efkproj)から見た相対パスで参照が保存されるようです。
そのため、出力ファイルとプロジェクトファイルのディレクトリが異なると外部ファイルを上手く読み込めません。
出力・プロジェクト共に同一ディレクトリ内に放り込んでおくのが確実かと思われます。
自分は上で参照パスを変えているので、「Assets/Particle/Effekseer」内に保存し、テクスチャはその中にtextureというディレクトリを作って参照しています。

まとめ

そんなわけで、フリーソフト「Effekseer」を使ってエフェクトを作ってみました!
単純なエフェクトならUnityで十分ですが、派手なものや複雑なものはEffekseerを活用して作っていきたいです。

「X-WeaponTrail」を使った武器の軌跡について

[2016/04/30]
記事を一部追記しました。

というわけで、文化の日なのでごろごろしているりべるんです。
文化的なことは全くしてないです!
一応、本屋にいって参考書等を読んできたので、それを文化的と捉えるならば・・・といったところです。

20150605_1

今回はAssetStoreにある「X-WeaponTrail」というアセットを使ってみました!
剣などの武器の軌跡をレンダリングしてくれるもので、すごく綺麗な軌跡ができます。

今まではUnity標準であるTrailRendererを使っていましたが、イマイチ使いにくかったり、レンダリングに不満があったりしました。
TrailRendererで軌跡を作るよりは、X-WeaponTrailを使った方がよさそうです。

導入と使い方

AssetStoreから無料でダウンロードできます。
https://www.assetstore.unity3d.com/jp/#!/content/20972

インポートすればプレハブがある上、デモシーンも付いてくるのでとっつきやすいです。
基本的に「X-WeaponTrail」というプレハブを付与するだけでOKです。

shot2ss20151103161523185

キャラクターのアニメーションに合わせる場合、Armatureの剣の動きに対応するBoneの子オブジェクトとして設定します。
メッシュにそのままくっ付けても追従しないので注意が必要です。
マリンパのモデルの場合、上のように「Bone_L_009」の子オブジェクトに設定しました。

プレハブの子オブジェクトに「StartPoint」と「EndPoint」があるので、これで軌跡の幅を調節します。
それぞれ赤と青の点が表示されるため分かりやすいです。

shot2ss20151103160637282

あとは再生して剣を動かすだけ!
設定で変える必要があるのは色くらいで、他は初期状態でも大丈夫な感じです。

shot2ss20151103161243006

通常のマテリアル以外に、歪みが出るマテリアルも提供されています。
重みのある武器でズドンとやる時に使うと味が出るかも。
単に「歪みが出せる」というだけでも貴重ですね。

攻撃時のみ軌跡を表示する方法

簡単な設定で奇跡の表示は出来ますが、現状ではレンダリングを止めることができません。
実際に使う場合は攻撃時のみ表示させることがほとんどです。
ということでちょっと考えてみました!

shot2ss20160430221425374

単純に X-WeaponTrail のプレハブを非アクティブにするだけではダメで、上のように残像が残ってしまいます。
スクリプトのパラメータを弄っても同じでした。

X-WeaponTrail のスクリプトを見ると、初期化時に専用のオブジェクトを生成し、そこで軌跡をレンダリングしているようです。
こいつの有効/無効を切り替えればいけそうです。
Player クラスから Find() するわけですが、オブジェクト名でFindするのは少々厳しそうです。
XWeaponTrail.cs の413行目付近でオブジェクトを生成しているので、そのオブジェクトにタグを設定します。

shot2ss20160430221441984

GameObject.tagに代入すれば動的にタグを設定できることはこれで初めて知ったりします。
タグマネージャに存在しないタグは弾かれてしまうので、予め登録しておきましょう。

あとはPlayerクラスで攻撃中のみアクティブにすればOKです。
単純に setActive() を使います。
AnimatorController を使っているのであればステートのタグで判定すれば良いだけなので、実装部分は割愛します。
以下の記事が参考になると思われます。

【再編集】Unity開発メモまとめ「Animator」

まとめ

短めですが、X-WeaponTrailを使って剣の軌跡を新しくしてみました!
有用なアセットを作成、配布して下さる方には感謝するばかりです。
自分も何か作れるようになってみたいところです。