2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

VitalRouter を VContainer と動かすサンプル

Posted at

VitalRouterVContainer と合わせて使うのに少し手間取ったのでサンプルコードを置いておきます。
とりあえず動かしてドキュメントを見たら何となく分かるはず。

サンプルコード

SampleCommand.cs
using VitalRouter;

// メッセージとして送るデータ
// メッセージを誰が受信するかは型によって判別されるので型定義が必須
public readonly struct SampleCommand : ICommand // 必ず ICommand をつける
{
    public int Value { get; }
    public SampleCommand(int value) => Value = value;
}

// record struct を使えるようにしている (https://zenn.dev/chorome/articles/ce2d86608e55fc) なら
// 以下のように1行で書けて便利 
// public readonly record struct SampleCommand(int Value) : ICommand;
SubscriberSample.cs
using VitalRouter;

// メッセージを受け取るクラスには [Routes] と partial が必須
[Routes] 
public partial class SubscriberSample
{
    // メッセージを受け取るメソッドには [Route] をつける
    [Route]
    private void On(SampleCommand cmd)
    {
        // SampleCommand を受け取ってログ出力するだけ
        UnityEngine.Debug.Log("SampleCommand を受け取りました。 Value = " + cmd.Value);
    }

    // 他のメッセージも受け取りたいなら型を変えてメソッドを作るだけ
    // [Route] private void On(AnotherSampleCommand cmd) { }
}
PublisherSample.cs
using System.Threading;
using System.Threading.Tasks;
using VitalRouter;

// メッセージを送るクラスでは ICommandPublisher を DI して、PublishAsync で送る
public class PublisherSample
{
    private ICommandPublisher _publisher;

    [VContainer.Inject]
    public PublisherSample(ICommandPublisher publisher)
    {
        _publisher = publisher;
    }

    public async ValueTask PublishAsync(CancellationToken token)
    {
        // ICommandPublisherに同期(Publish)は無いので必ず非同期(PublishAsync)
        await _publisher.PublishAsync(new SampleCommand(100), token);
    }
}
SampleLifetimeScope.cs
using UnityEngine;
using VContainer;
using VContainer.Unity;
using VitalRouter.VContainer;

// LifetimeScope のサンプル
// これを適当な GameObject にアタッチすればサンプルが動く
public class SampleLifetimeScope : LifetimeScope
{
    protected override void Configure(IContainerBuilder builder)
    {
        // メッセージを送る側は普通に登録する
        builder.Register<PublisherSample>(Lifetime.Singleton);

        // VitalRouter を DI する場合は RegisterVitalRouter を使う
        builder.RegisterVitalRouter(routing =>
        {
            // メッセージを受け取る側は Map で登録する
            routing.Map<SubscriberSample>();

            // もし MonoBehaviour ならMap ではなく MapComponent を使う
            // routing.MapComponent<SubscriberSample>();
        });
    }

    // テストのために Aキーが押されるたびに PublishAsync を呼び出す
    private async void Update()
    {
        if (Input.GetKeyDown(KeyCode.A))
        {
            var publisherSample = Container.Resolve<PublisherSample>();
            await publisherSample.PublishAsync(destroyCancellationToken);
        }
    }
}

VitalRouter とは

Unity と .NET で使えるメッセージングライブラリです。
Unity のメッセージングライブラリとしては MessagePipe が有名ですが使い勝手が全然違います。

VitalRouter の良いところ

受け取る側は属性をつけるだけ

MessagePipe では受け取るメッセージの種類の数だけ ISubscriber<> を DI して Subscribe します。
VitalRouter なら受け取る側は属性をつけるだけなのでコードが見やすくなります。

送る側は ICommandPublisher.PublishAsync で投げるだけ

MessagePipe では送るメッセージの種類ごとに IPublisher<> が必要です。さらに同期/非同期でも IPublisher<> と IAsyncPublisher<> を使い分けます。
VitalRouter なら ICommandPublisher だけであらゆるメッセージを投げられます。

VitalRouter の注意すべきところ

Publish が非同期のみ

メッセージを投げる側は全て非同期になります。開発途中で入れると書き換えていくのが大変かもしれません。
使うなら最初から入れておいた方が楽だと思います。

LifetimeScope で Map が必要

VContainer に登録するのに Register を使ってしまうとメッセージが届きません。
[Routes] をつけるのと Map にするのはセットで忘れないようにやりましょう。

VitalRouter を使うべきか

VContainer を使っているなら簡単に取り入れられておすすめです。
Subscribe が並んでいるのがどれだけ邪魔だったか、無くなってみてよく分かりました。

メッセージの送受信に ICommand の型定義を強制しているのが良いバランスになっていると思います。
使われている箇所を型から辿れる安心感があります。

MessagePipe は色々な機能がついているので完全互換ではありませんが、メッセージング機能としては VitalRouter で必要十分だと思います。
新規プロジェクトでは VitalRouter を最初の選択肢にしたいです。

2
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?