【Unity】剣の軌跡のつくりかた

#はじめに
こんにちは、中二病のZeniZeniです。
ゲームで剣を出すなら、かっこいい軌跡を出したいですよね？
色々と調べると、剣の軌跡の作り方はいろいろな方法があり、それぞれに長所・短所があります。
この記事では、それらの剣の軌跡の作り方をまとめてみようと思います。
VRでの使用を目的に調べていたので、VRに適しているかどうかの評価が多分に含まれます。

# TrailRendererを使う方法
## 参考資料
一番オーソドックスなのは、Trail Rendererを使う方法だと思います。（記事も多いです）
- [ユニティちゃんでわかるVRchatのためのunity教室 第12回　Trail Rendererで軌跡を描こう　トレイルレンダラー実装編](http://vrherokichi.com/2018/11/09/dai12kai/)
- [ケーキのPC情報集会所 【VRChat】トレイルレンダラー(Trail Renderer)を使って軌跡を描いてみよう♪♪](https://keiki002.com/vr/trail-vrc/)

AnimationEventやScript使わなくても、簡単な設定でそれっぽいのができるのは素晴らしいです。
Boothにもクオリティの高い作品が多く出展されています。
- [剣向け汎用トレイル](https://booth.pm/ja/items/1057062) Black.Cat's様作
- [霊刀睡蓮［屈折トレイル付き］](https://booth.pm/ja/items/1092786)　オニガワラインダストリ様作

具体的な使用方法は上記サイト様を参考にしてください。

##注意点 ねじれ問題

注意点なのですが、TrailRendererには**ねじれ問題**が存在します。
ねじれ問題とは、下図のように、Trailの折り返し時に、軌跡がぐちゃっとしてしまう問題です。
![Trailねじれ.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281560/93e420c5-a74d-9dd2-20a1-3a49b8fe59f6.gif)
原因は
- ノード間の感覚が狭い
- トレイルの幅が広い
ことであり、これらの調節である程度は改善できますが、完全にねじれを消すことは難しいです。
こちらの動画で詳しく紹介されています。
[【Unite Tokyo 2018】誘導ミサイル完全マスター](https://www.youtube.com/watch?v=t_4MbV2zIwg&t=2352s)

一般的な3Dゲームで使用する剣の軌跡であるならば、アニメーションが固定なのでTrailのオンオフで割と簡単にごまかせるのですが、VRだとそうはいきません。

###対処法
ねじれ問題の対処方法なのですが、二種類あると思っています。
一つは、上記動画で紹介されていますが、折り返し地点だけTrailを透明にしてごまかす方法です。
Shaderを自分で実装する必要がありますが、一つのTrailだけでできるのは楽でよいです。

もう一つが、「[剣向け汎用トレイル](https://booth.pm/ja/items/1057062) Black.Cat's様作」の実装法で、TrailRendererを大量に使用する方法です。
ねじれ問題は、トレイルの幅が広いと顕著に表れるので、幅の狭いTrailを大量に用いればぐちゃっとした軌跡ではなくなります。



# スクリプトからメッシュを生成する方法
こちらの記事で紹介されている方法です。
[Unityを使った3Dゲームの作り方（かめくめ） Unityでスクリプトから剣の軌跡を作成し表示する](Unityでスクリプトから剣の軌跡を作成し表示する)
スクリプトでメッシュを生成しているので、剣を振るアニメーションがどんなものでも調整いらずで軌跡を表示できます。

# ParticleSystemを使う方法
１番汎用性が高く、個性を出しやすいのはこの方法だと思います。
ただParticleSystemを使うといっても、方法はいろいろとあります。

## 剣の軌跡エフェクトを作って、アニメーションに合わせて発生させる方法
これは非VRのゲームで多く採用される方法だと思います。
下のGIFのようなエフェクトを剣を振るアニメーションに合わせて発生させます。
![slacheffect.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281560/5e9b92d4-3853-30da-7f32-597a051464df.gif)

このようなエフェクトは下図のような連番テクスチャを作成して、ParticleSystemの[Texture Sheet Animation](https://docs.unity3d.com/ja/2017.4/Manual/PartSysTexSheetAnimModule.html)の設定をすることでできます。
この連番テクスチャはAdobe AfterEffectを使用して作りました。
以下の動画が参考になります（英語字幕）。
[Game Effect Tutorial - Slash - Part 1/4 - DucVu FX](https://youtu.be/6LJVpNlwlkQ?list=PLZK8EDiZdQI71WEpxDeSNQtoL5kQPflM9)
![Slash_blend_01_sheet.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281560/e6c4fdba-0a0e-92aa-e005-7a71070bf733.png)
![bandicam 2019-12-11 16-43-27-974.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281560/05b076d9-3f35-3e84-76ad-728b61c01523.jpeg)

アニメーションに合わせて発生させる方法ですが、Animation Eventを使用することでできます。
Animation Eventの詳しい方はこちらを参考にしてください。
[[Unity] Animation Eventを使いこなそう！](https://qiita.com/aimy-07/items/58e77d3396ded286affc)



## 剣から細かいパーティクルを出して、軌跡っぽく見せる方法
こちらの画像みたいなことをします。
![FlameEnchantEffect_Moment.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281560/c8ca8691-d25f-2646-cb2a-e27f72cbec5b.jpeg)
動画はこちら
https://youtu.be/mU_uUo__vkw

###実装方法
剣から発生させたいParticleSystemを以下のように設定します。

![bandicam 2019-12-11 17-47-00-809.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281560/bb443e0a-d034-042f-e51a-071875034d3a.jpeg)
グローバルモジュール内のSimulationSpaceをWorldにします。
これがLocalだと、発生したパーティクルは剣との相対距離が一定のままになるので不自然になります。

![bandicam 2019-12-11 17-48-42-851.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281560/12cf2025-57d0-632d-c176-6a9948229165.jpeg)
Emissionモジュールの設定ですが、剣を振った時だけ軌跡を出したいというときには、Rate over TimeではなくRate over Distanceに値を入れてください。
ShapeモジュールではShapeをMesh RendererかSkinned Mesh Rendererにすることで、エフェクトの発生位置を二つ下にあるMeshに設定したMeshから発生させることができます。
使用するモデルがMesh RendererかSkinned Mesh Rendererのどちらを使っているかに注意してください。
TypeはVertexだと発生位置が偏りやすいので、EdgeかTriangleにするとよいです。

![bandicam 2019-12-11 20-28-20-170.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281560/f4c508c3-9896-7d6a-4435-daa0c67ce65c.jpeg)
Inherit VelocityモジュールのMultiplierの数値を0より大きくすることで、剣を振った方向にパーティクルを飛ばすことができるようになります。ModeはCurrentにすると剣の速度の影響を常に受けるようになってしまうので、Initialにするのがいいと思います。

### VFX Graphでやりたい場合
VFX GraphでパーティクルをSkinned Mesh RendererなどMeshから発生させたい場合、現状(2019年12月11日現在)のVFX Graphには標準でそのような機能はついていません。
Point Cacheがあるじゃんと思うかもしれませんが、あれは特定のメッシュの頂点情報を使用しており、Scene中の実際に使用するモデルの座標は参照できません。
しかしご安心ください、keijiroさんという方が公開しているUnityプロジェクトに、VFX GraphでSkinned Mesh Rendererを使用するサンプルプロジェクトがあります。
https://github.com/keijiro/Smrvfx
こちらを参考にしてください。（先ほど紹介した炎の軌跡エフェクトもVFX Graphで作成したものです）


#おわりに
他にも作る方法があるかと思いますが、とりあえず自分の知る範囲のことを紹介してみました。
他に作り方が見つかり（思いつき）次第追記していこうと思います。
個人的には「剣から細かいパーティクルを出して、軌跡っぽく見せる方法」が１番使い勝手が良くて好きですね。