ゲーム開発
Unity
UnrealEngine
C++
Blender
ゲーム数学
ゲームAI
グラフィックス
サウンド
アニメーション
GBDK
制作日記
IT関連
ツール開発
フロントエンド関連
サーバサイド関連
WordPress関連
ソフトウェア設計
おすすめ技術書
音楽
DTM
楽器・機材
ピアノ
ラーメン日記
四コマ漫画
その他
おすすめアイテム
おもしろコラム
  • ゲーム開発
    • Unity
    • UnrealEngine
    • C++
    • Blender
    • ゲーム数学
    • ゲームAI
    • グラフィックス
    • サウンド
    • アニメーション
    • GBDK
    • 制作日記
  • IT関連
    • ツール開発
    • フロントエンド関連
    • サーバサイド関連
    • WordPress関連
    • ソフトウェア設計
    • おすすめ技術書
  • 音楽
    • DTM
    • 楽器・機材
    • ピアノ
  • ラーメン日記
    • 四コマ漫画
      • その他
        • おすすめアイテム
        • おもしろコラム
      1. ホーム
      2. 20200509_02

      【Unity】Fungusを使ってセリフ機能を実装する

      Unityアセット関連Fungus
      2020-05-10

      マイケル
      マイケル
      どうもみなさんこんにちは!
      マイケルです!
      エレキベア
      エレキベア
      こんにちはクマ〜〜〜
      マイケル
      マイケル
      前回、オリジナルゲームを作成しているとの記事を書いたのですが、
      その中でもセリフ機能の実装について今回は紹介します!

      スクリーンショット 2020 05 09 14 16 20

      エレキベア
      エレキベア
      このセリフの部分のことクマね
      マイケル
      マイケル
      その通り!
      Fungusというアセットを使って実装しているんだ
      マイケル
      マイケル
      今回はFungusを使った実装方法について解説するよ!

      Fungusの導入方法

      マイケル
      マイケル
      導入はAssetStoreで「Fungus」を検索してインポートすれば完了です。
      エレキベア
      エレキベア
      簡単クマ〜〜〜

      Fungusを使った実装方法

      マイケル
      マイケル
      導入が完了したら以下の手順で会話機能を作成していきます。


      1. Flowchartの作成
      2. Characterオブジェクトの作成
      3. メッセージの作成

      Flowchartの作成

      マイケル
      マイケル
      会話の内容はフローチャートで作成していくのですが、そのためにFlowchartスクリプトを持つオブジェクトが最低一つは必要になります。
      マイケル
      マイケル
      Tools -> Fungus -> Create -> Flowchart
      より、オブジェクトを作成しましょう。
      エレキベア
      エレキベア
      きのこマークがついてかわいいクマ

      Characterオブジェクトの作成

      マイケル
      マイケル
      次に、会話させるキャラクターのオブジェクトを作成します。
      Flowchartと同じく
      Tools -> Fungus -> Create -> Character
      から作成しましょう!
      マイケル
      マイケル
      キャラクターオブジェクトには、名前とキャラクターの画像を設定します。

      メッセージの作成

      マイケル
      マイケル
      ここまでで準備は完了で、あとはメッセージを作っていきます。

      ・ゲーム開始時の出力

      マイケル
      マイケル
      まずは手始めにゲーム開始時のセリフを作成してみましょう!
      Tools -> Fungus -> Flowchart Window
      を選択するとフローチャートのウィンドウが開きます
      マイケル
      マイケル
      ブロックにはそれぞれ誰が何のセリフをいうか、等の情報を記述していきます
      ブロックは右クリック -> AddBrockから追加できます。
      エレキベア
      エレキベア
      セリフの呼び出しや選択パターンをここで分けるクマね
      マイケル
      マイケル
      その通りだよ
      ブロック内のExecute On Eventには呼び出されるタイミングを設定し、
      初期値の「Game Started」はゲーム開始時の出力処理になります。
      マイケル
      マイケル
      Commands欄にはSayコマンドでセリフを設定して、Callコマンドで呼びだすブロックを指定して会話の流れを作るのが基本となります!
      マイケル
      マイケル
      上記のように設定した状態でゲームをスタートするとセリフが出てきます。
      エレキベア
      エレキベア
      ゲームっぽいクマ〜〜〜!!
      マイケル
      マイケル
      セリフのUIも黒でおしゃれでいいよね

      ・キャラクターに話しかけた時

      マイケル
      マイケル
      次に自分で指定したタイミングで呼び出したい場合の設定方法です!
      ここでは例としてキャラクターに話しかけた時の設定とします
      マイケル
      マイケル
      フローチャート上はExecute On Event にMessage Receiveを指定し、メッセージに任意の値を設定してください。
      スクリプトからの呼び出しでメッセージの値を指定することで呼び出すことができるようになります!
      マイケル
      マイケル
      スクリプト側の設定としては、まずキャラクターの会話範囲を指定するためコライダを設定し、そこにスクリプトを作成してアタッチします。
      (下記では、「TalkArea」の箇所になります)
      public class TalkArea : MonoBehaviour
      {
          // ********************
          // * 変数定義          *
          // ********************
      
          /** コンポーネント */
          InputManager inputManager;
          FriendCtrl friendCtrl;
      
          /** 設定値 */
          public string messageId; // メッセージID
      
          /** 変数 */
          // 会話情報
          public class TalkInfo
          {
              public Transform talkTarget;  // 会話対称 
              public string messageId;      // メッセージID
          }
      
          // ********************
          // * 処理実行          *
          // ********************
      
          void Start()
          {
              inputManager = FindObjectOfType<InputManager>();
          }
      
          private void OnTriggerStay(Collider other)
          {
              // 衝突対称がプレイヤーかつ会話キーが押された場合
              if (other.tag == GameUtil.Const.TAG_PLAYER && inputManager.GetTalkKey())
              {
                  // プレイヤーの会話対称を設定
                  other.SendMessage("SetTalkInfo", GetTalkInfo(null));
              }
          }
      
          TalkInfo GetTalkInfo(Collider player)
          {
              TalkInfo talkInfo = new TalkInfo();
              talkInfo.talkTarget = transform;
              talkInfo.messageId = messageId;
              return talkInfo;
          }
      }
      マイケル
      マイケル
      会話範囲にプレイヤーが入っている時にボタンが押されるとプレイヤーのスクリプトの処理を呼び出すようにしています。
      プレイヤー側のスクリプト処理は以下の様に記述しています。
          /** 変数 */
          Transform talkTarget;   // 会話対象の位置
          string talkMessageId;   // メッセージID
      
          // ステート
          enum State
          {
              Walking, // 移動
              Talking, // ジャンプ
          };
          State state = State.Walking;     // 現在のステート
          State nextState = State.Walking; //次のステート
          
      ・・・略・・・
      
          void Update()
          {
              // ステートに応じた処理
              switch (state)
              {
                  case State.Walking:
                      Walking();
                      break;
                  case State.Talking:
                      Talking();
                      break;
              }
              // ステート遷移処理
              if (state != nextState)
              {
                  state = nextState;
                  switch (state)
                  {
                      case State.Walking:
                          WalkStart();
                          break;
                      case State.Talking:
                          TalkStart();
                          break;
                  }
              }
          }
      
      ・・・略・・・
      
          void Walking()
          {
      ・・・略・・・
              // 会話対称が設定されている場合、会話処理を行う
              if (talkTarget)
                  ChangeState(State.Talking);
      ・・・略・・・
            }
          
          // --------------- 会話 ---------------
      
          // 会話情報を設定する
          public void SetTalkInfo(TalkArea.TalkInfo talkInfo)
          {
              talkTarget = talkInfo.talkTarget;
              talkMessageId = talkInfo.messageId;
          }
      
          // 会話Start
          void TalkStart()
          {
      ・・・略・・・
      
              // 会話処理開始
              flowchart.SendFungusMessage(talkMessageId);
          }
      マイケル
      マイケル
      トリガーからの呼び出しで会話情報が設定された後、TalkStart()の部分でメッセージの呼び出しを行なっています。
      flowchart.SendFungusMessage()にメッセージを渡すことで呼び出すことができます。
      エレキベア
      エレキベア
      これで会話ができる様になったクマ!
      マイケル
      マイケル
      一旦できるようになったね
      でも、この状態だと会話している最中に他の処理が行われてしまうことがもありえるため、
      もう一歩、会話中の状態を取得して判定できるようにしていきます!
      マイケル
      マイケル
      フローチャート上で、下記の様に会話の始めと終わりでboolean型の変数を変更する様にします。
      変数は、フローチャート左下の+マークから追加できます!
      マイケル
      マイケル
      こうすることで追加したboolean型の変数で会話中かどうかを判定できるようになりました。
      スクリプトを下記の様に修正します。
      ・・・略・・・
      
          private void OnTriggerStay(Collider other)
          {
              // 会話中なら処理終了
              if (!flowchart.GetVariable<BooleanVariable>("Talking").Value)
                  return;
      
              // 衝突対称がプレイヤーかつ会話キーが押された場合
              if (other.tag == GameUtil.Const.TAG_PLAYER && inputManager.GetTalkKey())
              {
                  // プレイヤーの会話対称を設定
                  other.SendMessage("SetTalkInfo", GetTalkInfo(null));
                  // NPCの会話対称を設定
                  friendCtrl.SetTalkInfo(GetTalkInfo(other));
              }
          }
      
      ・・・略・・・
          /** 変数 */
          Transform talkTarget;   // 会話対象の位置
          string talkMessageId;   // メッセージID
          FriendCtrl talkFriend;  // 会話対象
      
      ・・・略・・・
          
          // --------------- 会話 ---------------
      
          // 会話情報を設定する
          public void SetTalkInfo(TalkArea.TalkInfo talkInfo)
          {
              talkTarget = talkInfo.talkTarget;
              talkMessageId = talkInfo.messageId;
              talkFriend = talkInfo.friendCtrl;
          }
      
          // 会話Start
          void TalkStart()
          {
      ・・・略・・・
      
              // 会話処理開始
              flowchart.SendFungusMessage(talkMessageId);
          }
      
          // 会話Update
          void Talking()
          {
              // 会話終了時
              if (!flowchart.GetVariable<BooleanVariable>("Talking").Value)
              {
                  // 会話対象の終了処理呼び出し
                  talkFriend.SendMessage("TalkEnd");
                  // 初期化
                  talkTarget = null;
                  talkMessageId = null;
                  talkFriend = null;
                  // 移動処理に遷移
                  ChangeState(State.Running);
              }
          }
      ・・・略・・・
          /** 変数 */
          Transform talkTarget;   // 会話対象の位置
          bool talkEnd;           // 会話終了判定
      
      ・・・略・・・
      
          // --------------- 会話 ---------------
      
          // 会話情報を設定する
          // (TalkAreaより呼び出される)
          public void SetTalkInfo(TalkArea.TalkInfo talkInfo)
          {
              talkTarget = talkInfo.talkTarget;
          }
      
          // 会話終了処理
          // (PlayerCtrlより呼び出される)
          public void TalkEnd()
          {
              talkEnd = true;
          }
      
      ・・・略・・・
      
          // 会話Update
          void Talking()
          {
              // 会話終了後、移動処理に遷移
              if (talkEnd)
              {
                  talkTarget = null;
                  ChangeState(State.Walking);
              }
          }
      マイケル
      マイケル
      上記のようにFlowchartで設定した変数を取得することで、会話中は処理を行わないなど判定を入れることができます!
      これで会話の処理は完成です!
      エレキベア
      エレキベア
      いい感じに会話できてるクマ〜〜〜!!

      おわりに

      マイケル
      マイケル
      会話機能アセットFungusの使い方を見ていきましたが、いかがだったでしょうか。
      エレキベア
      エレキベア
      ゲームっぽくなって楽しかったクマ〜〜〜〜
      マイケル
      マイケル
      Fungusには上記で紹介した処理以外にも機能がありますし、会話のアセット自体もFungus以外にたくさんあります。
      是非他の機能も調べてみてください!
      マイケル
      マイケル
      それでは今回はこの辺で!
      アデュー!!

      【Unity】Fungusを使ってセリフ機能を実装する 〜完〜


      Unityアセット関連Fungus
      2020-05-10

      関連記事
      【Unity】Timeline × Excelでスライドショーを効率よく制作する
      2024-10-31
      【Unity】Boidsアルゴリズムを用いて魚の群集シミュレーションを実装する
      2024-05-28
      【Unity】GoでのランキングAPI実装とVPSへのデプロイ方法についてまとめる【Go言語】
      2024-04-14
      【Unity】第二回 Wwiseを使用したサウンド制御 〜インタラクティブミュージック編〜
      2024-03-30
      【Unity】第一回 Wwiseを使用したサウンド制御 〜基本動作編〜
      2024-03-30
      【Unity】第二回 CRI ADXを使用したサウンド制御 〜インタラクティブミュージック編〜
      2024-03-28
      【Unity】第一回 CRI ADXを使用したサウンド制御 〜基本動作、周波数解析編〜
      2024-03-28
      【Unity】サウンドミドルウェアに依存しない設計を考える【CRI ADX・Wwise】
      2024-03-27