はじめに
今回はシューティングゲームなどで、 Particle System のように一つ一つのParticleの衝突判定を、 VFX Graph でしたいと思ったので、 VFX Graph の当たり判定について、自分が調べたことをまとめていきます。
こちらが使用しているバージョンです。
Unity: 2020.3.26f1
VFX: 10.8.1
ShaderGraph: 10.8.1
当たり判定実装方法
結論から言うと VFX Graph には、 Particle System のように衝突判定を追加する機能はありませんでした。
詳しくはこちらのサイトをhttps://forum.unity.com/threads/vfx-graph-collision.813231/
だからといってここで諦めるのは何なので、疑似的に当たり判定っぽいものを作っていきたいと思います。
手段
VFXに当たり判定っぽいものを実装する方法は、今回はVFX Graphをスクリプトで制御することでやっていきたいと思います。
VFX
こちらが VFX Graph のノードです。
DstPos
: 弾の目標地点
SrcPos
: 弾の発射地点
Color
: 弾のカラー
Speed
: 弾の速度
DstPos
からSrcPos
の差分から弾のベクトルを求めています。そして求めたベクトルを正規化しとSpeed
乗算することで、弾の速度をSpeed
で制御できる形にしています。
DstPos
からSrcPos
の差分から求めたベクトルの大きさを、弾の速度の大きさで割ることで弾がSrcPos
に到達する時間を求め、それをLifeTime
にしています。
スクリプト
サンプルコードでは、 IEnumerator
とyield return
を用いて一定秒数ごとにエフェクトを繰り返すようになってます。
弾の始点と弾のベクトルを元にray
を飛ばし、VFX Graphに値を返すようにすることで疑似的に当たり判定を再現しました。
サンプルコード
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.VFX;
/// <summary>
/// 一定時間ごとにBulletを撃つMonoBehaviourクラス
/// </summary>
public class BulletVFX : MonoBehaviour
{
[SerializeField] private VisualEffect _visualEffect; // 弾VisualEffect
[SerializeField] private Transform BulletTarget; // 弾が狙い撃ちする対象
[SerializeField] private float interval = 4f; // 弾を撃つ間隔
//Interval秒感覚でエフェクトを繰り返す
private IEnumerator Start()
{
while (true)
{
yield return new WaitForSeconds(interval);
_visualEffect.SendEvent("OnPlay");
Debug.Log("OnPlay");
}
}
void Update()
{
// Ray情報の作成
var origin = _visualEffect.GetVector3("SrcPos"); // 弾の始点
var direction = (BulletTarget.position - origin).normalized; // 弾の向きベクトル
var ray = new Ray(origin, direction);
// Raycast実行
if (Physics.Raycast(ray, out RaycastHit hit))
{
// Rayが当たった位置を弾の終点に設定
_visualEffect.SetVector3("DstPos", hit.point);
}
else
{
// 弾の終点の設定
_visualEffect.SetVector3("DstPos", BulletTarget.position);
}
}
}
実行結果
不可全ながらもVFX Graphで当たり判定っぽいものを実装できました。
問題点
無事にVFX Graphに当たり判定っぽいものを実装出来ましたが、いくつか問題点があります。
- スクリプトで制御しなければならないため、めんどくさい。
- 弾幕ゲーのようなものに実装するにはスクリプトやVFXが複雑になってしまう。
- 動いているものに対して、判定をとるのが難しい。
まとめ
VFX Graphには衝突判定そのものを実装する方法はない。スクリプトで制御することで疑似的に再現することは可能だが、いくつかの問題点がある。なので、エフェクトで衝突判定を行いたければ、 Particleシステム を利用するのがいい。
参考文献