Unity練習4

Unity練習2, 3の続きとなっています.ここでも引き続き次の記事を参考にする.

背景の表示

現状では,背景がなにもないので,背景の設定を行う.
Projectタブ内の"GamaManager.cs"を以下のように変更する.

using UnityEngine;
using UnityEngine.UI;
using System.Collections.Generic;
using System.Collections;

// MonoBehaviourを継承することでオブジェクトにコンポーネントとして
// アタッチすることができるようになる
public class GameManager : MonoBehaviour{
  // SerializeFieldと書くとprivateなパラメーターでも
  // インスペクター上で値を変更できる
  [SerializeField]
  private Text mainText;
  [SerializeField]
  private Text nameText;
  [SerializeField]
  private float captionSpeed = 0.2f;
  [SerializeField]
   private GameObject nextPageIcon;
   [SerializeField]
   private Image backgroundImage;
   [SerializeField]
   private string spritesDirectory = "Sprites/";

  
  // パラメーターを追加
   private const char SEPARATE_MAIN_START = '「';
   private const char SEPARATE_MAIN_END = '」';
   private Queue<char> _charQueue;
   private const char SEPARATE_PAGE = '&';
   private Queue<string> _pageQueue;
   private const char SEPARATE_COMMAND = '!';
   private const char COMMAND_SEPARATE_PARAM = '=';
   private const string COMMAND_BACKGROUND = "background";
   private const string COMMAND_SPRITE = "_sprite";
   private const string COMMAND_COLOR = "_color";
   

   private string _text = 
   "!background_sprite=\"background_sprite1\"&ともり「トーキョーは 薄暗い閃光放って」&ともり 「消耗した MPも回復できぬまま」&!background_sprite=\"background_sprite2\"!background_color=\"255,0,255\"&ともり「相当な 厄介者の説法聞いて」";
//"ともり「トーキョーは 薄暗い閃光放って」&ともり 「消耗した MPも回復できぬまま」";

   /**
   * 文を1文字ごとに区切り、キューに格納したものを返す
   */
   private Queue<char> SeparateString(string str){
       // 文字列をchar型の配列にする = 1文字ごとに区切る
       char[] chars = str.ToCharArray();
       Queue<char> charQueue = new Queue<char>();
       // foreach文で配列charsに格納された文字を全て取り出し
       // キューに加える
       foreach (char c in chars) charQueue.Enqueue(c);
       return charQueue;
   }

   private bool OutputChar(){
       if (_charQueue.Count <= 0){
           nextPageIcon.SetActive(true);
           return false;
       }
       mainText.text += _charQueue.Dequeue();
       return true;
   }


   // 文字送りするコルーチン
   private IEnumerator ShowChars(float wait){
       // OutputCharメソッドがfalseを返す(=キューが空になる)までループする
       while (OutputChar())
           // wait秒だけ待機
           yield return new WaitForSeconds(wait);
       // コルーチンを抜け出す
       yield break;
   }

   //全文表示
   private void OutputAllChar(){
      StopCoroutine(ShowChars(captionSpeed));
       while (OutputChar()) ;
       nextPageIcon.SetActive(true);
   }

   // MonoBehaviourを継承しているとき,毎フレーム呼ばれる
   private void Update(){
       // 左(=0)クリックされたらOnClickメソッドを呼び出し
       if (Input.GetMouseButtonDown(0)) OnClick();
   }

   //文字列を指定した区切り文字毎に区切り,キューに格納したものを返す
   private Queue<string> SeparateString(string str, char sep){
       string[] strs = str.Split(sep);
       Queue<string> queue = new Queue<string>();
       foreach (string l in strs) queue.Enqueue(l);
       return queue;
   }

   //初期化
   private void Init(){
       _pageQueue = SeparateString(_text, SEPARATE_PAGE);
       ShowNextPage();
   }

   //次のページの表示
   private bool ShowNextPage(){
       if (_pageQueue.Count <= 0) return false;
       // オブジェクトの表示/非表示を設定する
       nextPageIcon.SetActive(false);
       ReadLine(_pageQueue.Dequeue());
       return true;
   }

   private void Start(){
       Init();
   }

   //クリックしたときの処理
   private void OnClick(){
       if (_charQueue.Count > 0) OutputAllChar();
       else{
           if (!ShowNextPage()){
               // UnityエディタのPlayモードを終了する
               UnityEditor.EditorApplication.isPlaying = false;
           }
       }
   }

   private void SetBackgroundImage(string cmd, string parameter){
       // 空白を削除し、背景コマンドの文字列も削除する
       cmd = cmd.Replace(" ", "").Replace(COMMAND_BACKGROUND, "");
       // ダブルクォーテーションで囲われた部分だけを取り出す
       parameter = parameter.Substring(parameter.IndexOf('"') + 1, parameter.LastIndexOf('"') - parameter.IndexOf('"') - 1);
       switch (cmd){
           case COMMAND_SPRITE:
               // Resourcesフォルダからスプライトを読み込み、インスタンス化する
               Sprite sp = Instantiate(Resources.Load<Sprite>(spritesDirectory + parameter));
               // 背景画像にインスタンス化したスプライトを設定する
               backgroundImage.sprite = sp;
               break;
           case COMMAND_COLOR:
               // 空白を削除し、カンマで文字を分ける
               string[] ps = parameter.Replace(" ", "").Split(',');
               // 分けた文字列(=引数)が4つ以上あるなら
               if (ps.Length > 3)
                   // 透明度も設定する
                   // 文字列をbyte型に直し、色を作成する
                   backgroundImage.color = new Color32(byte.Parse(ps[0]), byte.Parse(ps[1]),
                                                   byte.Parse(ps[2]), byte.Parse(ps[3]));
               else
                   backgroundImage.color = new Color32(byte.Parse(ps[0]), byte.Parse(ps[1]), byte.Parse(ps[2]), 255);
               break;
       }
   }

   /**
   * コマンドの読み出し
   */
   private void ReadCommand(string cmdLine){
       // 最初の「!」を削除する
       cmdLine = cmdLine.Remove(0, 1);
       Queue<string> cmdQueue = SeparateString(cmdLine, SEPARATE_COMMAND);
       foreach (string cmd in cmdQueue){
           // 「=」で分ける
           string[] cmds = cmd.Split(COMMAND_SEPARATE_PARAM);
           // もし背景コマンドの文字列が含まれていたら
           if (cmds[0].Contains(COMMAND_BACKGROUND))
               SetBackgroundImage(cmds[0], cmds[1]);
       }
   }

   private void ReadLine(string text){
       // 最初が「!」だったら
       if (text[0].Equals(SEPARATE_COMMAND)){
           ReadCommand(text);
           ShowNextPage();
           return;
       }
       string[] ts = text.Split(SEPARATE_MAIN_START);
       string name = ts[0];
       string main = ts[1].Remove(ts[1].LastIndexOf(SEPARATE_MAIN_END));
       nameText.text = name;
       mainText.text = "";
       _charQueue = SeparateString(main);
       StartCoroutine(ShowChars(captionSpeed));
   }

}

すると,Inspector上で"GameManager"は次のようになる.

画像1

初期状態ではBackgound ImageはNone(Image)になっているので,BackgroundPanelに変更する.

次に背景画像を用意する.
ProjectタブのAssets/Resources/Spritesに移動し,任意のスプライトを二つ新たに作成する(すでに作成したページ送りアイコンが1つ入っている).

(右クリック)→[create]→[sprites]→(好きな形を選ぶ)

作成した二つのスプライトをそれぞれ
"background_sprite1","background_sprite2"に名前を変更する.

次にHierarchy上でCanvas/GamaMager/BackgroungPanelを選択してInspectorタブに"BackgroundPanel"を表示させる.すると次のようになっている.

画像2

Inspector上のImage TypeがSlicedになっているので,これをSimpleに変更する.すると,そのしたにUse Sprite Meshが出てくるのでチェックを入れる(普通の背景画像を扱う際にはいらない).
ここまで作業した後の画面を次に示す.

画像3

実行してみる.

画像4

画像5

画像6

ここで,三つ目の画面で背景が変化しているのは.
"GameManager.cs"における次の部分によるものである.(枠に収めるために改行している)
ここはコードの解説なので,読み飛ばしていただいても問題はない.

  private const char SEPARATE_COMMAND = '!';
  private const char COMMAND_SEPARATE_PARAM = '=';
  private const string COMMAND_BACKGROUND = "background";
  private const string COMMAND_SPRITE = "_sprite";
  private const string COMMAND_COLOR = "_color";
  private string _text = 
"!background_sprite=\"background_sprite1\"
&ともり「トーキョーは 薄暗い閃光放って」
&ともり 「消耗した MPも回復できぬまま」
&!background_sprite=\"background_sprite2
\"!background_color=\"255,0,255\"
&ともり「相当な 厄介者の説法聞いて」";
    private void SetBackgroundImage(string cmd, string parameter){
       // 空白を削除し、背景コマンドの文字列も削除する
       cmd = cmd.Replace(" ", "").Replace(COMMAND_BACKGROUND, "");
       // ダブルクォーテーションで囲われた部分だけを取り出す
       parameter = parameter.Substring(parameter.IndexOf('"')+1, 
              parameter.LastIndexOf('"') - parameter.IndexOf('"') - 1);
       switch (cmd){
           case COMMAND_SPRITE:
               // Resourcesフォルダからスプライトを読み込み、
               //インスタンス化する
               Sprite sp = Instantiate(Resources.Load<Sprite>(spritesDirectory + parameter));
               // 背景画像にインスタンス化したスプライトを設定する
               backgroundImage.sprite = sp;
               break;
           case COMMAND_COLOR:
               // 空白を削除し、カンマで文字を分ける
               string[] ps = parameter.Replace(" ", "").Split(',');
               // 分けた文字列(=引数)が4つ以上あるなら
               if (ps.Length > 3)
                   // 透明度も設定する
                   // 文字列をbyte型に直し、色を作成する
                   backgroundImage.color = new Color32(byte.Parse(ps[0]), byte.Parse(ps[1]),
                                                   byte.Parse(ps[2]), byte.Parse(ps[3]));
               else
                   backgroundImage.color = new Color32(byte.Parse(ps[0]), byte.Parse(ps[1]), byte.Parse(ps[2]), 255);
               break;
       }
   }
/**
   * コマンドの読み出し
   */
   private void ReadCommand(string cmdLine){
       // 最初の「!」を削除する
       cmdLine = cmdLine.Remove(0, 1);
       Queue<string> cmdQueue = SeparateString(cmdLine, SEPARATE_COMMAND);
       foreach (string cmd in cmdQueue){
           // 「=」で分ける
           string[] cmds = cmd.Split(COMMAND_SEPARATE_PARAM);
           // もし背景コマンドの文字列が含まれていたら
           if (cmds[0].Contains(COMMAND_BACKGROUND))
               SetBackgroundImage(cmds[0], cmds[1]);
       }
   }
private void ReadLine(string text){
       // 最初が「!」だったら
       if (text[0].Equals(SEPARATE_COMMAND)){
           ReadCommand(text);
           ShowNextPage();
           return;
       }
       string[] ts = text.Split(SEPARATE_MAIN_START);
       string name = ts[0];
       string main = ts[1].Remove(ts[1].LastIndexOf(SEPARATE_MAIN_END));
       nameText.text = name;
       mainText.text = "";
       _charQueue = SeparateString(main);
       StartCoroutine(ShowChars(captionSpeed));
   }

最初にReadCommandで,先頭の'!'が削除されて次のようになる.

"background_sprite=\"background_sprite1\"&ともり
「トーキョーは 薄暗い閃光放って」&ともり 「消耗した MPも回復できぬまま」&!background_sprite=\"background_sprite2\
"!background_color=\"255,0,255\"&ともり「相当な 厄介者の説法聞いて」"

次に,'='で文を分けてcmdsに格納する.

cmds[0]="background_sprite"
cmds[1]=\"background_sprite1\"&ともり「トーキョーは 薄暗い閃光放って」&ともり 「消耗した MPも回復できぬまま」&!background_sprite
cmds[2]=\"background_sprite2\"!background_color
cmds[3]=\"255,0,255\"&ともり「相当な 厄介者の説法聞いて」"

ここで,cmds[0]が"background"を含んでいるので,
SetBackgroundImage(cmds[0], cmds[1])を呼ぶ.

cmd=cmds[0]から空白と"background"が取り除かれ,次のようになる.(SetBackgroundImageメソッド)

cmd="_sprite"

次に,parameter=cmds[1]の""に囲まれているところのみを取り出す.

parameter="background_sprite1\"

cmd="_sprite"なのでparameter="background_sprite1\"を表示させるといったような操作を行い,背景の操作をしている.

色がマゼンタなのは,"255,0,255,255"がマゼンタを表すからである
コマンドの使用方法を以下に簡単に示す.

・「!」を最初につける(全コマンド共通)
・「!background_sprite="《スプライト名》"」で背景画像を設定
・「!background_color="《r》,《g》,《b》,《a》"」で色を設定

また,画像があるフォルダを"Sprites Directory"で指定することもできる.


立ち絵の表示

立ち絵を表示させるために"GamaManager.cs"を次のように変更する.(背景画像の表示と立ち絵の表示で共通の部分はSetBackgroundImageメソッドの外に出して独立のメソッドにする)

using UnityEngine;
using UnityEngine.UI;
using System.Collections.Generic;
using System.Collections;

// MonoBehaviourを継承することでオブジェクトにコンポーネントとして
// アタッチすることができるようになる
public class GameManager : MonoBehaviour{
  // SerializeFieldと書くとprivateなパラメーターでも
  // インスペクター上で値を変更できる
  [SerializeField]
  private Text mainText;
  [SerializeField]
  private Text nameText;
  [SerializeField]
  private float captionSpeed = 0.2f;
  [SerializeField]
   private GameObject nextPageIcon;
   [SerializeField]
   private Image backgroundImage;
   [SerializeField]
   private string spritesDirectory = "Sprites/";

  
  // パラメーターを追加
   private const char SEPARATE_MAIN_START = '「';
   private const char SEPARATE_MAIN_END = '」';
   private Queue<char> _charQueue;
   private const char SEPARATE_PAGE = '&';
   private Queue<string> _pageQueue;
   private const char SEPARATE_COMMAND = '!';
   private const char COMMAND_SEPARATE_PARAM = '=';
   private const string COMMAND_BACKGROUND = "background";
   private const string COMMAND_SPRITE = "_sprite";
   private const string COMMAND_COLOR = "_color";
   

   private string _text = 
   "!background_sprite=\"background_sprite1\"&ともり「トーキョーは 薄暗い閃光放って」&ともり 「消耗した MPも回復できぬまま」&!background_sprite=\"background_sprite2\"!background_color=\"255,0,255\"&ともり「相当な 厄介者の説法聞いて」";
//"ともり「トーキョーは 薄暗い閃光放って」&ともり 「消耗した MPも回復できぬまま」";

   /**
   * 文を1文字ごとに区切り、キューに格納したものを返す
   */
   private Queue<char> SeparateString(string str){
       // 文字列をchar型の配列にする = 1文字ごとに区切る
       char[] chars = str.ToCharArray();
       Queue<char> charQueue = new Queue<char>();
       // foreach文で配列charsに格納された文字を全て取り出し
       // キューに加える
       foreach (char c in chars) charQueue.Enqueue(c);
       return charQueue;
   }

   private bool OutputChar(){
       if (_charQueue.Count <= 0){
           nextPageIcon.SetActive(true);
           return false;
       }
       mainText.text += _charQueue.Dequeue();
       return true;
   }


   // 文字送りするコルーチン
   private IEnumerator ShowChars(float wait){
       // OutputCharメソッドがfalseを返す(=キューが空になる)までループする
       while (OutputChar())
           // wait秒だけ待機
           yield return new WaitForSeconds(wait);
       // コルーチンを抜け出す
       yield break;
   }

   //全文表示
   private void OutputAllChar(){
      StopCoroutine(ShowChars(captionSpeed));
       while (OutputChar()) ;
       nextPageIcon.SetActive(true);
   }

   // MonoBehaviourを継承しているとき,毎フレーム呼ばれる
   private void Update(){
       // 左(=0)クリックされたらOnClickメソッドを呼び出し
       if (Input.GetMouseButtonDown(0)) OnClick();
   }

   //文字列を指定した区切り文字毎に区切り,キューに格納したものを返す
   private Queue<string> SeparateString(string str, char sep){
       string[] strs = str.Split(sep);
       Queue<string> queue = new Queue<string>();
       foreach (string l in strs) queue.Enqueue(l);
       return queue;
   }

   //初期化
   private void Init(){
       _pageQueue = SeparateString(_text, SEPARATE_PAGE);
       ShowNextPage();
   }

   //次のページの表示
   private bool ShowNextPage(){
       if (_pageQueue.Count <= 0) return false;
       // オブジェクトの表示/非表示を設定する
       nextPageIcon.SetActive(false);
       ReadLine(_pageQueue.Dequeue());
       return true;
   }

   private void Start(){
       Init();
   }

   //クリックしたときの処理
   private void OnClick(){
       if (_charQueue.Count > 0) OutputAllChar();
       else{
           if (!ShowNextPage()){
               // UnityエディタのPlayモードを終了する
               UnityEditor.EditorApplication.isPlaying = false;
           }
       }
   }

   /* コマンドの読み出し*/
   private void ReadCommand(string cmdLine){
       // 最初の「!」を削除する
       cmdLine = cmdLine.Remove(0, 1);
       Queue<string> cmdQueue = SeparateString(cmdLine, SEPARATE_COMMAND);
       foreach (string cmd in cmdQueue){
           // 「=」で分ける
           string[] cmds = cmd.Split(COMMAND_SEPARATE_PARAM);
           // もし背景コマンドの文字列が含まれていたら
           if (cmds[0].Contains(COMMAND_BACKGROUND))
               SetBackgroundImage(cmds[0], cmds[1]);
       }
   }

   private void ReadLine(string text){
       // 最初が「!」だったら
       if (text[0].Equals(SEPARATE_COMMAND)){
           ReadCommand(text);
           ShowNextPage();
           return;
       }
       string[] ts = text.Split(SEPARATE_MAIN_START);
       string name = ts[0];
       string main = ts[1].Remove(ts[1].LastIndexOf(SEPARATE_MAIN_END));
       nameText.text = name;
       mainText.text = "";
       _charQueue = SeparateString(main);
       StartCoroutine(ShowChars(captionSpeed));
   }

   /* スプライトをファイルから読み出し、インスタンス化する*/
   private Sprite LoadSprite(string name){
       return Instantiate(Resources.Load<Sprite>(spritesDirectory + name));
   }

   /*パラメーターから色を作成する*/
   private Color ParameterToColor(string parameter){
       string[] ps = parameter.Replace(" ", "").Split(',');
       if (ps.Length > 3)
           return new Color32(byte.Parse(ps[0]), byte.Parse(ps[1]), byte.Parse(ps[2]), byte.Parse(ps[3]));
       else
           return new Color32(byte.Parse(ps[0]), byte.Parse(ps[1]), byte.Parse(ps[2]), 255);
   }

   /**
   * 画像の設定
   */
   private void SetImage(string cmd, string parameter, Image image){
       cmd = cmd.Replace(" ", "");
       parameter = parameter.Substring(parameter.IndexOf('"') + 1, parameter.LastIndexOf('"') - parameter.IndexOf('"') - 1);
       switch (cmd){
           case COMMAND_SPRITE:
               image.sprite = LoadSprite(parameter);
               break;
           case COMMAND_COLOR:
               image.color = ParameterToColor(parameter);
               break;
       }
   }

   private void SetBackgroundImage(string cmd, string parameter){
       cmd = cmd.Replace(COMMAND_BACKGROUND, "");
       SetImage(cmd, parameter, backgroundImage);
   }

}

書き換えた後も,今のままでは動作は変化しないので,一度実行してみて変化していないかを確かめる.

次に表示する立ち絵を作成する.
Hierarchyタブで
Canvas/GameManager/BackGroundPanel/CharacterImages
を選択し,次の手順を行う.

(右クリック)→[UI]→[Image]

作られてものの名前を"CharacterImage"に変更する.ここまで行った画面を次に示す.

画像8

この状態でInspector上のSource Imageを見ると,None(Sprite)になっている.Inspector上にUse Sprite MeshとPreserve Aspectを追加するために,このSource Imageを何かしら選択する(筆者の画面では"background_sprite1"を選択している).すると次のような画面になる.

画像8

Inaspector上に新しく表れたUse Sprite MeshとPreserve Aspectにチェックを入れる(普通の立ち絵の時にUse Sprite Meshを用いる必要はない).
次に,ProjectタブでAssets/Resources/Prefabsを選択し,Hierarchyタブの"CharacterImge"をPrefabsにドラッグ&ドロップするそして,Hierarchyタブ上で"CharacterImage"を削除する.このとき,次のようになる.

画像9

次に,立ち絵を表示するコードに変更する."GameManager.cs"を次のように変更する.(うまくコードを成型できなかったので現在は保留中.飛ばしても問題はない)


テキストファイルからデータを読み込む​

長いパラメータをコードに入れると可読性が下がるうえに実用性が低いので,テキストファイルから読み取りできるようにする.
次のように"GamaManager.cs"を変更する.

using UnityEngine;
using UnityEngine.UI;
using System.Collections.Generic;
using System.Collections;

// MonoBehaviourを継承することでオブジェクトにコンポーネントとして
// アタッチすることができるようになる
public class GameManager : MonoBehaviour{
  // SerializeFieldと書くとprivateなパラメーターでも
  // インスペクター上で値を変更できる
  [SerializeField]
  private Text mainText;
  [SerializeField]
  private Text nameText;
  [SerializeField]
  private float captionSpeed = 0.2f;
  [SerializeField]
   private GameObject nextPageIcon;
   [SerializeField]
   private Image backgroundImage;
   [SerializeField]
   private string spritesDirectory = "Sprites/";
   [SerializeField]
   private GameObject characterImages;
   [SerializeField]
   private string prefabsDirectory = "Prefabs/";
   [SerializeField]
   private string textFile = "Texts/Scenario";

   private List<Image> _charaImageList = new List<Image>();

  
  // パラメーターを追加
   private const char SEPARATE_MAIN_START = '「';
   private const char SEPARATE_MAIN_END = '」';
   private Queue<char> _charQueue = new Queue<char>();
   private const char SEPARATE_PAGE = '&';
   private Queue<string> _pageQueue;
   private const char SEPARATE_COMMAND = '!';
   private const char COMMAND_SEPARATE_PARAM = '=';
   private const string COMMAND_BACKGROUND = "background";
   private const string COMMAND_SPRITE = "_sprite";
   private const string COMMAND_COLOR = "_color";
   private const string COMMAND_CHARACTER_IMAGE = "charaimg";
   private const string COMMAND_SIZE = "_size";
   private const string COMMAND_POSITION = "_pos";
   private const string COMMAND_ROTATION = "_rotate";
   private const string CHARACTER_IMAGE_PREFAB = "CharacterImage";
   
   private string _text = "";

/*
   private string _text = 
   "!background_sprite=\"background_sprite1\"!charaimg_sprite=\"polygon\"=\"background_sprite2\""+
      "!charaimg_size=\"polygon\"=\"500, 500, 1\"&ともり「トーキョーは 薄暗い閃光放って」&ともり 「消耗した MPも回復できぬまま」" +
      "&!background_sprite=\"background_sprite2\"!background_color=\"255,0,255\"!charaimg_pos=\"polygon\"=\"-500, 500, 0\"&ともり「相当な 厄介者の説法聞いて」";
+/

   /**
   * 文を1文字ごとに区切り、キューに格納したものを返す
   */
   private Queue<char> SeparateString(string str){
       // 文字列をchar型の配列にする = 1文字ごとに区切る
       char[] chars = str.ToCharArray();
       Queue<char> charQueue = new Queue<char>();
       // foreach文で配列charsに格納された文字を全て取り出し
       // キューに加える
       foreach (char c in chars) charQueue.Enqueue(c);
       return charQueue;
   }

   private bool OutputChar(){
       if (_charQueue.Count <= 0){
           nextPageIcon.SetActive(true);
           return false;
       }
       mainText.text += _charQueue.Dequeue();
       return true;
   }


   // 文字送りするコルーチン
   private IEnumerator ShowChars(float wait){
       // OutputCharメソッドがfalseを返す(=キューが空になる)までループする
       while (OutputChar())
           // wait秒だけ待機
           yield return new WaitForSeconds(wait);
       // コルーチンを抜け出す
       yield break;
   }

   //全文表示
   private void OutputAllChar(){
      StopCoroutine(ShowChars(captionSpeed));
       while (OutputChar()) ;
       nextPageIcon.SetActive(true);
   }

   // MonoBehaviourを継承しているとき,毎フレーム呼ばれる
   private void Update(){
       // 左(=0)クリックされたらOnClickメソッドを呼び出し
       if (Input.GetMouseButtonDown(0)) OnClick();
   }

   //文字列を指定した区切り文字毎に区切り,キューに格納したものを返す
   private Queue<string> SeparateString(string str, char sep){
       string[] strs = str.Split(sep);
       Queue<string> queue = new Queue<string>();
       foreach (string l in strs) queue.Enqueue(l);
       return queue;
   }

   //次のページの表示
   private bool ShowNextPage(){
       if (_pageQueue.Count <= 0) return false;
       // オブジェクトの表示/非表示を設定する
       nextPageIcon.SetActive(false);
       ReadLine(_pageQueue.Dequeue());
       return true;
   }

   private void Start(){
       Init();
   }

   //クリックしたときの処理
   private void OnClick(){
       if (_charQueue.Count > 0) OutputAllChar();
       else{
           if (!ShowNextPage()){
               // UnityエディタのPlayモードを終了する
               UnityEditor.EditorApplication.isPlaying = false;
           }
       }
   }


   private void ReadLine(string text){
       // 最初が「!」だったら
       if (text[0].Equals(SEPARATE_COMMAND)){
           ReadCommand(text);
           ShowNextPage();
           return;
       }
       string[] ts = text.Split(SEPARATE_MAIN_START);
       string name = ts[0];
       string main = ts[1].Remove(ts[1].LastIndexOf(SEPARATE_MAIN_END));
       nameText.text = name;
       mainText.text = "";
       _charQueue = SeparateString(main);
       StartCoroutine(ShowChars(captionSpeed));
   }

   /* スプライトをファイルから読み出し、インスタンス化する*/
   private Sprite LoadSprite(string name){
       return Instantiate(Resources.Load<Sprite>(spritesDirectory + name));
   }

   /*パラメーターから色を作成する*/
   private Color ParameterToColor(string parameter){
       string[] ps = parameter.Replace(" ", "").Split(',');
       if (ps.Length > 3)
           return new Color32(byte.Parse(ps[0]), byte.Parse(ps[1]), byte.Parse(ps[2]), byte.Parse(ps[3]));
       else
           return new Color32(byte.Parse(ps[0]), byte.Parse(ps[1]), byte.Parse(ps[2]), 255);
   }

   

   private void SetBackgroundImage(string cmd, string parameter){
       cmd = cmd.Replace(COMMAND_BACKGROUND, "");
       SetImage(cmd, parameter, backgroundImage);
   }

       /* 立ち絵の設定*/
   private void SetCharacterImage(string name, string cmd, string parameter){
       cmd = cmd.Replace(COMMAND_CHARACTER_IMAGE, "");
       name = name.Substring(name.IndexOf('"') + 1, name.LastIndexOf('"') - name.IndexOf('"') - 1);
       Image image = _charaImageList.Find(n => n.name == name);
       if (image == null){
           image = Instantiate(Resources.Load<Image>(prefabsDirectory + CHARACTER_IMAGE_PREFAB), characterImages.transform);
           image.name = name;
           _charaImageList.Add(image);
       }
       SetImage(cmd, parameter, image);
   }

/*パラメーターからベクトルを取得する*/
   private Vector3 ParameterToVector3(string parameter){
       string[] ps = parameter.Replace(" ", "").Split(',');
       return new Vector3(float.Parse(ps[0]), float.Parse(ps[1]), float.Parse(ps[2]));
   }

   //コマンドの呼び出し
   private void ReadCommand(string cmdLine){
       cmdLine = cmdLine.Remove(0, 1);
       Queue<string> cmdQueue = SeparateString(cmdLine, SEPARATE_COMMAND);
       foreach (string cmd in cmdQueue){
           string[] cmds = cmd.Split(COMMAND_SEPARATE_PARAM);
           if (cmds[0].Contains(COMMAND_BACKGROUND))
               SetBackgroundImage(cmds[0], cmds[1]);
           if (cmds[0].Contains(COMMAND_CHARACTER_IMAGE))
               SetCharacterImage(cmds[1], cmds[0], cmds[2]);
       }
   }

   //画像の設定
   private void SetImage(string cmd, string parameter, Image image){
       cmd = cmd.Replace(" ", "");
       parameter = parameter.Substring(parameter.IndexOf('"') + 1, parameter.LastIndexOf('"') - parameter.IndexOf('"') - 1);
       switch (cmd){
           case COMMAND_SPRITE:
               image.sprite = LoadSprite(parameter);
               break;
           case COMMAND_COLOR:
               image.color = ParameterToColor(parameter);
               break;
           case COMMAND_SIZE:
               image.GetComponent<RectTransform>().sizeDelta = ParameterToVector3(parameter);
               break;
           case COMMAND_POSITION:
               image.GetComponent<RectTransform>().anchoredPosition = ParameterToVector3(parameter);
               break;
           case COMMAND_ROTATION:
               image.GetComponent<RectTransform>().eulerAngles = ParameterToVector3(parameter);
               break;
       }
   }

   private string LoadTextFile(string fname){
       TextAsset textasset = Resources.Load<TextAsset>(fname);
       return textasset.text.Replace("\n", "").Replace("\r", "");
   }

   //初期化
   private void Init(){
       _text = LoadTextFile(textFile);
       _pageQueue = SeparateString(_text, SEPARATE_PAGE);
       ShowNextPage();
   }


}

このように"GamaManager.cs"を変更したら.Projectタブの
Assets/Resources/Textsフォルダ内に"Scenario.txt"というテキストファイルを作成する.これはUnity上では行えないので,メモ帳などで行う.(筆者はvscodeでTextsフォルダを開いて.txtを作成した)
例えば次のように"Scenario.txt"を記述する

!background_sprite="background_sprite1"
!charaimg_sprite="polygon"="background_sprite2"
!charaimg_size="polygon"="500, 500, 1"

&ともり「トーキョーは 薄暗い閃光放って」
&ともり 「消耗した MPも回復できぬまま」

&!background_sprite="background_sprite2"
!background_color="255,0,255"
!charaimg_pos="polygon"="-500, 500, 0"

&ともり「相当な 厄介者の説法聞いて」

このとき,改行は読み込む際に削除するようにしているので,いくら改行を挟んでもよいが,空白は意味をもつので注意する.
実行してみると,今まで作成してきたものとほぼ同じ動きをする(背景に切り替えに一クリック余分に必要となっている.)




この記事が気に入ったらサポートをしてみませんか?