🎼

【Unity】ScenarioFlowによるシナリオ実装#1-5(ScenarioBookの読み方2)

2023/04/19に公開

はじめに

こんにちは.伊都アキラです.
前回の記事では,呼び出すScenarioMethodの情報を保持しているScenarioBookの構造と,その使い方について解説していました.

今回の記事は,その続きになります.

Fluent interface

前回,IScenarioBookIScenarioPageIScenarioSentenceの構造について解説しました.
お気づきの方もいらっしゃるかもしれませんが,IScenarioBookの中で特定のIScenarioPageを指定するためのOpenToメソッドや,IScenarioPageの中で特定のIScenarioSentenceを指定するためのPointToの返り値の型は,voidではなくそれぞれIScenarioBookIScenarioPageです.

これは,OpenToPointToが呼び出されたとき,呼び出したインスタンスそのものが返されることを意図しています.
そして,これを利用することで以下のようなコードを書くことができます.

        scenarioBook
            .OpenTo(1)
            .ReadPage()
            .PointTo(2)
            .ReadSentence()
            .OnRead();

このコードでは,あるIScenarioBookに対して,1番目のIScenarioPageを開き,2番目のIScenarioSentenceを指定して実行しています.

このように,インスタンスに対する設定を行うメソッドが適切なインターフェースを返すことで,連続した設定を行うことができ,かつ見通しも良くなるような設計はFluent interfaceと呼ばれます.

以下のようにGameManager.csStart内のコードを変更して,実行してみましょう.
狙ったIScenarioSetenceを実行する処理を,簡潔に記述することができていると思います.

GameManager.cs
public class GameManager : MonoBehaviour
{
    private void Start()
    {
      //中略
      
        //ScenarioMethodをすべて実行
        //ReadScenarioBook(scenarioBook);
        //コメントアウト

        //IScenarioBookの1番目のIScenarioPageを開き,
        //2番目のIScenarioSentenceを指定して実行
        scenarioBook
            .OpenTo(1)
            .ReadPage()
            .PointTo(2)
            .ReadSentence()
            .OnRead();

        //IScenarioPageはそのまま,
        //0番目のIScenarioSentenceを指定して実行
        scenarioBook
            .ReadPage()
            .PointTo(0)
            .ReadSentence()
            .OnRead();

        //IScenarioBookの2番目のIScenarioPageを開き,
        //3番目のIScenarioSentenceを指定して実行
        scenarioBook
            .OpenTo(2)
            .ReadPage()
            .PointTo(3)
            .ReadSentence()
            .OnRead();
    }
}


GameManager.cs実行結果

拡張メソッド

IScenarioBookIScenarioPageにはたくさんのメソッドが定義されています.
ScenarioFlowは,その中でも,次のページを開いたり,次のページがあるかどうかを確かめたりするといった,よく使われるであろう処理を実行するための拡張メソッドをいくつか提供しています.

IScenarioBook

以下,IScenarioBookで使用できる拡張メソッドです.

IScenarioBook Flip()

一つ後のIScenarioPageを開きます.

        //2つのコードは等価
        scenarioBook.OpenTo(scenarioBook.CurrentIndex + 1);
        scenarioBook.Flip();

bool Remain()

Flip可能かどうかを返します.

        //2つのコードは等価
        if (scenarioBook.CurrentIndex < scenarioBook.MaxIndex)
        {
            //Do something
        }
        if (scenarioBook.Remain())
        {
            //Do something
        }

IScenarioBook Reset

IScenarioBook内の全てのIScenarioPageにおいて0番目のIScenarioSentenceを指定し,0番目のIScenarioPageを開きます.

        //2つのコードは等価
        foreach(var scenarioPage in scenarioBook.ReadAll())
        {
            scenarioPage.PointTo(0);
        }
        scenarioBook.OpenTo(0);

        scenarioBook.Reset();

IScenarioPage

以下,IScenarioPageで使用できる拡張メソッドです.

IScenarioBook Follow()

1つ後のIScenarioSentenceを指定します.

        //2つのコードは等価
        scenarioPage.PointTo(scenarioPage.CurrentIndex + 1);
        scenarioPage.Follow();

bool Remain()

Follow可能かどうかを返します.

        //2つのコードは等価
        if (scenarioPage.CurrentIndex < scenarioPage.MaxIndex)
        {
            //Do something
        }
        if (scenarioPage.Remain())
        {
            //Do something
        }

ラベルの付加

IScenarioBookには,OpenLabelというメソッドがありました.
ScenarioBook中にある,指定したラベルが紐づけられているScenarioSentenceを指定するためのメソッドです.

このメソッドを利用するためには,ソースファイルを記述する時点でラベルを付加しておく必要があります.
以下のようなソースファイルを準備しましょう.

1番左の列に<Label>シンボルを,その1つ右の列ラベルの名前を書きます.
すると,OpenLabelによって,狙ったラベルが付加されているScenarioMethodを実行することができます.
以下のようにGameManager.csを変更して,実行してみましょう.

GameManager.cs
public class GameManager : MonoBehaviour
{
    //中略

    private void Start()
    {
      //中略 
      
        //ScenarioMethodをすべて実行
        //ReadScenarioBook(scenarioBook);
        //コメントアウト

        scenarioBook.OpenLabel("ラベルB").ReadPage().ReadSentence().OnRead();

        scenarioBook.OpenLabel("ラベルA").ReadPage().ReadSentence().OnRead();
    }
}


GameManager.cs実行結果

おわりに

前回と今回の記事では,ScenarioBookの構造とその使い方について解説しました.

実践的には,TaskFlowScenarioBookReaderにScenarioBookを渡せば適切にScenarioBookを読み込んでシナリオ進行をしてくれます.ですから,究極的にはソースファイルの書き方さえ覚えておけば,ScenarioBook自体の使い方を意識する必要はありません.

ただ,シナリオ進行に関して何かしらの拡張を行う場合,ScenarioBookを直接扱う機会があるかもしれません.

今回の記事はこれで終わりです.
最後までお読みいただきありがとうございました.

Discussion