質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Q&A

0回答

879閲覧

List化した複数のTimelineAssetを任意のタイミングで再生したい・PlayableDirectorの仕組みについて教えてほしい

gariyaro

総合スコア8

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

0グッド

0クリップ

投稿2020/11/07 09:34

前提・実現したいこと

Unityにて2Dアドベンチャーゲームを制作している初心者です。
言語はC#です。
テキストによる会話シーンとTimelineを使ったイベントシーンの挿入を交互に行いたいと考えています。
複数のTimelineAssetをリストにアタッチし、スクリプトからTimelineAssetを再生しようと考えたのですが、最初に再生したTimelineAsset以降はうまく再生されません。

以前にも同じ質問(https://teratail.com/questions/298818)を行ったのですがsakura_hana様から頂きましたご指示を元に前回からコードを幾つか書き換えた結果、追記・修正を行うには文章量が多すぎる為、新たに設けさせていただきます。

発生している問題・エラーメッセージ

インスペクター上で各フラグが分岐した時点でのPlayableDirectorのPlayableの項目を確認するとTimelineAssetの切り替えは行われていました。
また、2度目のTimelineAssetが再生されるフラグ4が立った際にDebug.Log(playableDirector.state);でPlayableDirectorのstateを調べたところPlayingのままでした、Updateの中に書いているので、フラグ4が立った上でif (playableDirector.state != PlayState.Playing)の条件分岐を設定しtrueの時にアニメーションが再生されるようにしているので、2回目以降のアニメが再生されない理由は理解できたのですが、対策方法が分かりません。
PlayableDirectorには1つのTimelineAssetしか再生できないということなのでしょうか
また、PlayableDirectorがTimelineAssetの再生を終える度に初期設定にリセットする方法はないのでしょうか。
皆様のお知恵をお借りしたく存じます。

該当のソースコード①

scnarioNumを変更し、scenarioスクリプトをOnにすることで再生するセリフを変更します
フラグが立つことでListにアタッチされたTimelineAssetを再生します

C#

1using System.Collections; 2using System.Collections.Generic; 3using UnityEngine; 4using UnityEngine.UI; 5using UnityEngine.Playables; 6using UnityEngine.Timeline; 7 8public class NPC6 : MonoBehaviour //NPC6を管理するスクリプトです 9{ 10 public TimelineAsset[] timelines; 11 public PlayableDirector playableDirector; 12 public int scnarioNum = 0; 13 GameObject player; 14 PlayerScript playerScript; 15 [SerializeField] 16 Scenario6 scenario; 17 18 public bool IsDone() //Timeline再生終了検知用bool 19 { 20 return playableDirector.time >= playableDirector.duration; 21 } 22 // Start is called before the first frame update 23 void Start() 24 { 25 playableDirector = GetComponent<PlayableDirector>(); 26 player = GameObject.Find("Player"); 27 playerScript = player.GetComponent<PlayerScript>(); 28 never_met = false; 29 } 30void Update() 31 { 32 //初日の処理 33 if (TimeManager.Dates == 0) 34 { 35 if (FlagManager.Instance.flags[0] == true) //フラグ0を立てると 36 { 37 if (playableDirector.state != PlayState.Playing) //アニメ再生中でないなら 38 { 39 Debug.Log("アニメ1開始"); 40 playableDirector.Play(timelines[0]); 41 playerScript.characterState = PlayerScript.CharacterState.pose; 42 scnarioNum = 0; 43 } 44 if (IsDone()) 45 { 46 //playableDirector.Stop(); 47 scenario.enabled = true; 48 } 49 } 50 else if (FlagManager.Instance.flags[1] == true) //フラグ1が立つと 51 { 52 if (FlagManager.Instance.flags[2] == true) //フラグ2が立つと 53 { 54 scnarioNum = 1; 55 scenario.enabled = true; 56 } 57 if (FlagManager.Instance.flags[3] == true) //フラグ3が立つと 58 { 59 scnarioNum = 2; 60 scenario.enabled = true; 61 } 62 } 63 if (FlagManager.Instance.flags[4] == true) //フラグ4が立つと 64 Debug.Log(playableDirector.state); 65 { 66 if (playableDirector.state != PlayState.Playing) //アニメ再生中でないなら 67 { 68 Debug.Log("アニメ2開始"); 69 //playableDirector.time = 0; 70 //playableDirector.enabled = true; 71 playableDirector.Play(timelines[1]); 72 } 73 if (IsDone()) 74 { 75 Debug.Log("アニメ2再生終了"); 76 } 77 } 78 } 79 }

該当のソースコード②

NPCスクリプトのscnarioNumに応じたセリフを表示します
シナリオが最後まで呼ばれるとOffになります、scnarioNumに応じてフラグを立てたり消したりします

C#

1using System.Collections; 2using System.Collections.Generic; 3using UnityEngine; 4using TMPro; 5using UnityEngine.UI; 6using UnityEngine.SceneManagement; 7public class Scenario6 : MonoBehaviour //NPC6のシナリオ及びフラグの建築を管理するスクリプトです 8{ 9 [SerializeField] 10 string[] currentScenario; 11 public string[] scenarios; //文章を格納するstring型の配列 12 public string[] scenarios2; 13 public string[] scenarios3; 14 public string[] scenarios4; 15 16 private GameObject messageText; 17 [SerializeField] TextMeshProUGUI uiText; 18 [SerializeField] private GameObject ansewerPanel; 19 20 [SerializeField] 21 [Range(0.001f, 0.3f)] 22 float intervalForCharacterDisplay = 0.05f; //表示する文字の間隔 23 24 private string currentText = string.Empty; //現在の文章 25 private float timeUntilDisplay = 0; //表示までの時間 26 private float timeElapsed = 1; //経過した時間 27 private int currentLine = 0; //現在表示している文章番号 28 private int lastUpdateCharacter = -1; //最後に更新する文字 29 GameObject player; 30 PlayerScript playerScript; 31 [SerializeField] 32 private GameObject Caretaker; 33 NPC6 npc1; 34 [SerializeField] 35 private bool Reload = false; 36 AudioSource audioSource; 37 38 public bool IsCompleteDisplayText 39 { 40 get { return Time.time > timeElapsed + timeUntilDisplay; } 41 } 42 43 // Start is called before the first frame update 44 void Start() 45 { 46 messageText = GameObject.Find("MessageText"); 47 uiText = messageText.GetComponent<TextMeshProUGUI>(); 48 player = GameObject.Find("Player"); 49 playerScript = player.GetComponent<PlayerScript>(); 50 npc1 = Caretaker.GetComponent<NPC6>(); 51 audioSource = GetComponent<AudioSource>(); 52 } 53 54 // Update is called once per frame 55 void Update() 56 { 57 if (npc1.scnarioNum == 0) 58 { 59 if (Reload == false) 60 { 61 currentScenario = scenarios; 62 currentLine = 0; //currentLineをゼロに戻す 63 SetNextLine(); 64 Reload = true; 65 } 66 LoadScenario(); 67 ScenarioEnd(); 68 } 69 70 if (npc1.scnarioNum == 1) 71 { 72 if (Reload == false) 73 { 74 currentScenario = scenarios2; 75 currentLine = 0; //currentLineをゼロに戻す 76 SetNextLine(); 77 Reload = true; 78 } 79 LoadScenario(); 80 ScenarioEnd(); 81 } 82 83 if (npc1.scnarioNum == 2) 84 { 85 if (Reload == false) 86 { 87 currentScenario = scenarios3; 88 currentLine = 0; //currentLineをゼロに戻す 89 SetNextLine(); 90 Reload = true; 91 } 92 LoadScenario(); 93 ScenarioEnd(); 94 } 95 } 96 public void SetNextLine() 97 { 98 currentText = currentScenario[currentLine]; 99 timeUntilDisplay = currentText.Length * intervalForCharacterDisplay; 100 timeElapsed = Time.time; 101 currentLine++; 102 lastUpdateCharacter = -1; 103 } 104 105 public void LoadScenario() 106 { 107 // 文字の表示が完了してるなら次の行を表示する 108 if (IsCompleteDisplayText) 109 { 110 if (currentLine < currentScenario.Length && Input.GetKeyDown(KeyCode.Z)) 111 { 112 SetNextLine(); 113 } 114 } 115 else 116 { 117 // 完了してないなら文字をすべて表示する 118 if (Input.GetKeyDown(KeyCode.Z)) 119 { 120 timeUntilDisplay = 0; 121 } 122 } 123 //↓の「Mathf.Clamp01」は 124 int displayCharacterCount = (int)(Mathf.Clamp01((Time.time - timeElapsed) / timeUntilDisplay) * currentText.Length); 125 if (displayCharacterCount != lastUpdateCharacter)//再生中の文字 126 { 127 uiText.text = currentText.Substring(0, displayCharacterCount); 128 lastUpdateCharacter = displayCharacterCount; 129 } 130 } 131 public void ScenarioEnd() 132 { 133 if (currentScenario.Length == currentLine) //シナリオが最後まで読まれると~ 134 { 135 Debug.Log("管理人セリフえんど"); 136 currentText = string.Empty; 137 playerScript.characterState = PlayerScript.CharacterState.normal; 138 FlagManager.Instance.talking = false; 139 Reload = false; 140 this.enabled = false; 141 142 //以下、初日のみ行う処理 143 if (TimeManager.Dates == 0) 144 { 145 if (npc1.scnarioNum == 0) 146 { 147 FlagManager.Instance.flags[0] = false; //フラグ0を消す 148 FlagManager.Instance.flags[1] = true; //フラグ1を立てる 149 ansewerPanel.SetActive(true); 150 } 151 if (npc1.scnarioNum == 1|npc1.scnarioNum == 2) 152 { 153 FlagManager.Instance.flags[1] = false; //フラグ1を消す 154 FlagManager.Instance.flags[4] = true; //フラグ4を立てる 155 } 156 } 157 } 158 } 159}

試したこと

補足情報(FW/ツールのバージョンなど)

Unity 2019.4.1f1

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだ回答がついていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問