Unityで非再生時にPlayableAPIを使用してParticleSystemを確認しやすくしてみる

AvatarPosted by

本記事は GRIPHONE Advent Calendar 2022 15日目の記事です。

こんにちは、Unityエンジニアの上岡です。
この記事では、UnityのPlayableAPIを使って非再生時にParticleSystemを確認しやすくする方法について説明します。

これが必要になった経緯としましては
自分が現在関わっているプロジェクトでは、3Dモデルなどの確認を非再生状態で行えるようにしています。
モーションもPlayableAPIを使用して非再生状態で確認できるようになっているのですが
ParticleSystemを使用したエフェクトも一緒に確認しようとしたところ
そのままではうまくいかなかったためです。

ParticleSystemは、そのままヒエラルキーに置いた場合は
選択されていないと動作が止まってしまいます。
これでは確認ツールとしては使えないので、対応する必要ができました。

PlayableAPIについては、詳しき記事が沢山あるので
ここでは説明は省かせてもらいます。

早速コードです。
まずはPlayableBehaviourを継承したクラスを用意します。

using UnityEngine;
using UnityEngine.Playables;

public class ParticleSystemPlayable : PlayableBehaviour
{
    private ParticleSystem _particleSystem;

    public void Initialize(ParticleSystem particleSystem)
    {
        _particleSystem = particleSystem;
        _particleSystem.Stop();
        if (_particleSystem.useAutoRandomSeed) 
        {
            _particleSystem.randomSeed = 0;
            _particleSystem.useAutoRandomSeed = false;
        }
    }

    public override void OnBehaviourPlay(Playable playable, FrameData info)
    {
        if (_particleSystem != null)
        {
            _particleSystem.Play();
        }
    }

    public override void OnBehaviourPause(Playable playable, FrameData info)
    {
        if (_particleSystem != null)
        {
            _particleSystem.Stop();
        }
    }

    public override void ProcessFrame(Playable playable, FrameData info, object playerData)
    {
        if (_particleSystem != null)
        {
            _particleSystem.Simulate(info.deltaTime, true, false);
        }
    }
}

次に、ParticleSystemを確認したいときに
そのPrefabにAddComponentするスクリプトを用意します。

#if UNITY_EDITOR
using UnityEngine;
using UnityEngine.Playables;

[ExecuteAlways]
public class ParticleTester : MonoBehaviour
{
    private PlayableGraph _playableGraph;
    
    private void Awake()
    {
        var ps = GetComponent<ParticleSystem>();
        if (ps == null) return;
        
        _playableGraph = PlayableGraph.Create();
        var particleSystemPlayable = ScriptPlayable<ParticleSystemPlayable>.Create(_playableGraph, 0);
        particleSystemPlayable.GetBehaviour().Initialize(ps);
        var output = ScriptPlayableOutput.Create(_playableGraph, "ParticleSystem");
        output.SetSourcePlayable(particleSystemPlayable);
    }

    private void OnEnable()
    {
        _playableGraph.Play();
    }

    private void OnDisable()
    {
        _playableGraph.Stop();
    }

    private void OnDestroy()
    {
        if (_playableGraph.IsValid())
        {
            _playableGraph.Destroy();
        }
    }
}
#endif

このスクリプトをPrefabにAddComponentすれば
ヒエラルキーで選択をしていなくても、ParticleSystemは停止しなくなります。

これらは完全に確認ツール用のコードですので、AddComponentしたまま実行した場合のことはあまり考えていないコードになっています。

以上、Unityで非再生時にPlayableAPIを使用してParticleSystemを確認しやすくしてみる方法でした。
あまり需要はないかもしれませんが、ツール類を作っている方々のお役に立てれば幸いです。

明日以降も記事は続きますのでお楽しみに。