ビジュアルノベルアセットFungusにコマンドを追加してカスタマイズする

この記事はUnity アセット真夏のアドベントカレンダー 2018 Summer!の2日目の記事です。

Fungusについて

Fungus はフリーのビジュアルノベルアセットで、高機能・高評価のアセットです。
簡単な概要についてはフリーのビジュアルノベルアセットのFungusが便利で紹介しています。
また、応用として、フリーのビジュアルノベルアセットFungusを使ってRPGのイベントを作る でも紹介しています。

概要

Fungusはビジュアルノベルアセットですが、RPGの会話機能に使ったり、フローチャートの機能を使ってイベントを制御したりすることができます。

Fungusのフローチャート

Fungusのコマンドは以下のようにたくさん用意されていますが、独自のコマンドを追加することにより、プロジェクトに適した使い方ができます。

Fungusのコマンド群

コマンドの追加方法

コマンドのソースはFungus/Scripts/Commandsに配置されています。
例えば、音楽を再生するPlay Musicコマンドを抜粋すると以下のようになっています。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
[CommandInfo("Audio",
"Play Music",
"Plays looping game music. If any game music is already playing, it is stopped. Game music will continue playing across scene loads.")]
[AddComponentMenu("")]
public class PlayMusic : Command
{
[SerializeField] protected AudioClip musicClip;
[SerializeField] protected float atTime;
[SerializeField] protected bool loop = true;
[SerializeField] protected float fadeDuration = 1f;

public override void OnEnter(){
var musicManager = FungusManager.Instance.MusicManager;
float startTime = Mathf.Max(0, atTime);
musicManager.PlayMusic(musicClip, loop, fadeDuration, startTime);
Continue();
}
public override string GetSummary(){
if (musicClip == null){
return "Error: No music clip selected";
}
return musicClip.name;
}

このソースからわかるようにCommandクラスを継承したクラスを作成し、CommandInfoを追加することによって、コマンドとして認識されるようです。
CommandInfoの第一引数がカテゴリ、第二引数が表示名、第三引数がヘルプのテキストです。
クラスのメンバにSerializeFieldを追加した変数はInspectorから設定できるようになります。

OnEnterメソッドが実際にコマンドとして実行されるメソッドです。最後にContinue()を呼ぶことにより、次のコマンドに遷移します。

GetSummaryメソッドを実装するとコマンドリストに表示されるサマリを変更できます。Play Musicに関してはAudio Clipがあればその音楽ファイル名を表示しています。

もし、プロジェクトで独自のSoundManagerクラスなどを実装している場合、このPlay MusicPlay SEを参考に作り直すと良いです。
ちなみにFungusはデフォルトだと音楽再生などをするとFungusManagerというDontDestroyOnloadされたマネージャが生成されます。

Play Musicコマンド

if コマンドを追加する

コマンドの中でもifは特殊なコマンドです。
ここでは仮にDEBUG_HOGEがdefineされていたらifが成立するようなデバッグ用のif コマンドを作ってみます。
CommandクラスではなくConditionを継承し、bool EvaluateCondition()bool HasNeededProperties()を実装すればif コマンドが作れます。
できたのが以下です。EvaluateCondition()の返り値がtrueだとif内に入ります。
HasNeededProperties()についてはこれがfalseを返すと条件に関係なくifの中に入ってしまうので、ここでは常にtrueを返しておきます。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
namespace Fungus {
/// <summary>
/// If the test expression is true, execute the following command block.
/// </summary>
[CommandInfo("Flow", "DebugIf", "If define DEBUG_HOGE")]
[AddComponentMenu("")]
public class DebugIf : Condition {

protected override bool EvaluateCondition() {
#if DEBUG_HOGE
return true;
#else
return false;
#endif
}
protected override bool HasNeededProperties() {
return true;
}
}
}

DEBUGIfコマンド

まとめ

Fungusはオープンソースでもあるのでソースコードが見やすく、他の人が拡張しやすいように設計されています。
そのため、今回のようにコマンドを追加したりして、自身のプロジェクトに合うようにカスタマイズするととても便利になります。
ただ、あまり本体のコードを書き換えるとバージョンアップに対応できないので注意が必要です。
私は2017年9月からVer.3.6を使用していますが、今回の検証のためVer.3.9.1をダウンロードしたところ、コマンドが増えていたりとバージョンアップは頻繁に行われているようです。

使用したバージョン

  • Unity 2018.2.0f2
  • Fungus 3.9.1
Unityカテゴリの記事
Color SpaceがLinearのときUIの透明度が正しくならない
History Inspectorの紹介
History Inspectorの紹介
敵AIとビジュアルスクリプティング
Chronosを使った感想
コンポーネントの順番をスクリプトから並び替える
Smart Inspectorの紹介
Kris' Favorite Assets が便利
キー操作でUIのナビゲーションをループさせる
TextMeshProのSprite Assetを更新する
UnityPhysicsDebugDraw2D が便利
色管理を考える
細かいTips
ビルドスクリプトを書く
AnimatorのCulling Modeでハマった話
Vectrosityを使ってUGUI上で線や円のアニメーションをする
スプレッドシートからjsonデータを読み込む
Skinned Mesh Renderer の Boundsについて
シーンごとにビルド結果の容量を出す
シーンビューにクオリティ設定のスライダーを出すエディタ拡張
ビルド結果のFile headersが大きい理由
フリーのビジュアルノベルアセットFungusを使ってRPGのイベントを作る
Move To View を改良する
フリーのビジュアルノベルアセットのFungusが便利
Visual Studio で保存時にフォーマットする
スプレッドシートからデータを読み込む
Easy Save2 で シリアライズされたクラスを保存する
ShaderでSpriteの色相をシフトする
Sprite、Texture の 色相をシフトする
uGUIのButtonをクリック時にハイライトのままになる
uGUIのCanvas Groupを使って透過処理をしたり、操作を制限する
自作のコンフィグ画面に必要なもの
uGUIでトグルなボタンを作る
uGUI で動的にボタンを作る
Easy Save2 を使ってみる
csv読み込んで ローカライズ
LoadLevelAdditive で共通シーンを加算
画面全体に色をかける
Any State でどこからでも遷移できるようにする
iTween のStop ではまる
sprite の multiple で 境界がおかしくなる
2D画面に線を引く Line Renderer
Renderer の Materials を スクリプトから設定する
背景をスクロールさせる