Autoボタンを押すと、話が進む。画面をクリックするとAutoシステムが停止する。
Unityで作るノベルゲーム第6回は、Autoモードの実装です。
UIボタンを1度押すと、一定の間隔で自動的にテキストや立ち絵を進めていきます。
- 第0回:「画面サイズ変更、ボタンとテキスト作成、UIの操作 」
- 第1回:「Excel(表計算ソフト)でCSVを作成して読み込む」
- 第2回:「画面クリックした回数だけCSVのテキストを表示する」
- 第3回:「CSVのテキストをスクリプトでUITextを操作、画面に表示する」
- 第4回:「ボタンクリックで画面クリック判定しない方法」
- 第5回:「CSVでテキスト、画像、音をパスで認識して呼び起こす方法」
- 第6回: 【本記事】
- 第7回:「クイックセーブ・ロードの実装」
- 第8回:「改造されないセーブ・ロード実装」
ゲームにおけるオートモードは、言葉の通り、ユーザーがアクションをしなくても自動的に操作する機能になります。
ノベルゲームにおけるオート機能は、ゲーム内のテキストやストーリーを自動的に進めるための機能です。
通常、ノベルゲームではプレイヤーがクリックやボタン操作を行ってテキストを進めていきますが、オートモードを使用すると、テキストが自動的に表示され、一定の速度で進行します。
オートモードを導入するメリットは、プレイヤーがクリック操作が煩わしいと感じているときにストーリーの流れやイベントの展開を自動的に楽しむことができます。
また、プレイヤーがテキストを読む時間を省略するために使用されることがあります。これにより、プレイヤーはゲームの進行をより効率的に進めることができます。
オートモードは、速度や停止条件をなどの拡張がユーザーによって設定することができます。このシステム開発は第9回で公表しています。(現在、鋭意制作中)
- ゲーム全般のオート機能を作成したい
- ボタンクリックでオートモードを停止したい
- ノベルゲームを作りたい
Invoke
オート機能は前述したように、一定の速度で自動的に操作をする機能です。
そこで、Unityでは、Invokeを使うことを推奨します。
UnityのInvokeは、指定された時間の経過後にメソッドを呼び出すための機能です。このメソッドを使用することで、一定の遅延を持たせて実行したり、繰り返し実行することができます。
単発の処理には、Invokeを使用します。
delayTimeで指定された時間(秒単位)の経過後にMethodNameというメソッドが呼び出されます。
Invoke("MethodName", delayTime);
繰り返しの処理には、InvokeRepeatingを使用します。
initialDelayで指定された時間(秒単位)の遅延後に初回のメソッド呼び出しを行い、以降はrepeatRateで指定された時間の間隔でメソッドが繰り返し実行されます。
InvokeRepeating("MethodName", initialDelay, repeatRate);
これらの処理を停止するには、CancelInvokeを使用します。
CancelInvoke("MethodName");
本製作では、別のアプローチとして、onClickのクリックイベントを拡張するして、「.onClick.Invoke()」を使用しています。
参考ページ:「UI.Button-onClick – Unity スクリプトリファレンス」
Invokeの詳細は以下の記事で紹介しています。
Auto機能
Auto機能には、Invokeを使うことを理解したところで、ここからは、ソースコードにInvokeとonclickを追加していきます。
今回は、csvの読み込みを左クリックと、Autoの2種します。
つまり、csvを表示する同じコードを2回書く必要があります。
void Update()
{
if(Input.GetMouseButtonDown(0))
{
A.text = csvData[i][0];
B.text = csvData[i][1];
}
}
void Auto()
{
A.text = csvData[i][0];
B.text = csvData[i][1];
}
もちろん、2回書いても正しく処理されますが、スクリプト全体が長くなってスマートではないです。
したがって、今回は、関数「Loadcsv()」にcsvを呼び起こすようにして、それぞれに渡して処理をします。
ソースコード
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using System.IO;
using UnityEngine.EventSystems; //ボタンがクリックで反応する
public class csvcontroler : MonoBehaviour
{
public TextAsset csvFile; //CSVファイル
public static List<string[]> csvData = new List<string[]>(); //csvファイルの中身を入れるリスト
public static int i = 0;
bool Auto;
public Text Nametext;
public Text Logtext;
public Image LeftImg;
public Image RightImg;
private AudioSource audio;
private AudioClip Sound;
public Button AutoBtn;
void Start()
{
//csvファイル
csvFile = Resources.Load("Data") as TextAsset; //Resourcesにあるcsvファイルを格納
StringReader reader = new StringReader(csvFile.text); //TextAssetをStringReaderに変換
while (reader.Peek() != -1)
{
string line = reader.ReadLine(); //1行ずつ読み込み
csvData.Add(line.Split(',')); //csvDataリストに追加
}
//音声を取得
audio = GetComponent<AudioSource>();
}
void Update()
{
//ボタンを押したときは画面クリック無効
if (EventSystem.current.IsPointerOverGameObject())
{
return;
}
//左クリックで Loadcsv();メソッドを読み込む
if (!Auto && Input.GetMouseButtonDown(0)) //!Autoは、左クリックでAuto解除するときに処理しないように
{
Loadcsv();
}
//Autoシステム解除
if (Input.GetMouseButtonDown(1) || Auto && Input.GetMouseButtonDown(0)) // 右クリックを検知
{
Auto = false; // 自動モード停止
AutoBtn.image.color = Color.white; // 色を元に戻す
Debug.Log("停止!" + "フラグ::::" + Auto);
}
}
//CSVを呼び出す(ローカルのみの処理)
private void Loadcsv()
{
Debug.Log("人物:" + csvData[i][0] + "セリフ:" + csvData[i][1]);
Nametext.text = csvData[i][0];
Logtext.text = csvData[i][1];
LeftImg.sprite = Resources.Load<Sprite>(csvData[i][2]);
RightImg.sprite = Resources.Load<Sprite>(csvData[i][3]);
//音声データ
Sound = (AudioClip)Resources.Load(csvData[i][4]);
audio.PlayOneShot(Sound);
if (i <= csvData.Count)
{
i++;
}
}
//Autoシステム
public void Autobtn()
{
Invoke("Automode", 2.0f); //2秒後に"Automode"メソッドを読み込む
Auto = true;
Debug.Log("開始!" + "フラグ::::" + Auto);
AutoBtn.image.color = Color.gray; //ボタンの色をグレーにする。
}
//Invokeで使う
void Automode()
{
if (!Auto)
{
return; // Autoがfalseなら処理を中断
}
Loadcsv();
// Autobtnを押し続けるスクリプト
AutoBtn.onClick.Invoke();
}
}
思い通りのゲームが作れない
Unityでゲーム開発しているけど完成しない。
技術的な壁や知識不足が原因で、思い描いたゲームを実現するのは難しいです。
しかし、Udemyは動画で実践的なゲーム開発を解説していて、
購入した講座は再生・停止・スキップなどが可能なオンデマンド形式なので、
専門的な内容を自分のペースで学習できます。
Unityの機能を網羅したいや作りたいゲームがある人はUdemy学習を取り入れましょう。
数多くある講座の中から特におすすめな講座を3つ紹介します。
初夏のセール開催中!(5月23日まで)
対象のコースが1300円から。
Unityのはじめの一歩としておすすめ。開発例に物理挙動やアニメーションを使用しているので、今後の開発が円滑になる。
トランプを題材にした講座。カードゲームやボードゲーム開発に応用可能
UnityエンジンのインストールやC#の文法に加えて、App StoreとGoogle Playにゲームをリリース方法を解説。
解説
初めに、名前空間を追加します。
「Unity」に搭載されているUIを使用するため、「using UnityEngine.UI;」を追加します。
csvを読み込んだり、書きこんだり、データを列挙できるようにする「using System.IO;」の追加絵押します。
UIを押したときに同時に画面押下の判定が出ないように「using UnityEngine.EventSystems;」を追加します。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using System.IO;
using UnityEngine.EventSystems; //ボタンがクリックで反応する
続いて、変数を定義します。
「csvFile」は、CSVファイルを格納するためのTextAsset型の変数です。
「csvData」は 、CSVファイルの内容を格納するためのList型の変数です。
「i」は、現在のCSVデータのインデックスを表すint型変数です。
「Auto」は、オートモードの有無を表すbool型変数です。
「Nametext」、「Logtext」、「LeftImg」、「RightImg」は、それぞれテキストと立ち絵を表示するUI変数です。
「audio」は、音声再生のためのAudioSourceコンポーネントを格納する変数です。
「Sound」は、音声データを格納するためのAudioClip型の変数です。
「AutoBtn」は、自動モードを切り替えるためのボタンを格納する変数です。
public TextAsset csvFile; //CSVファイル
public static List<string[]> csvData = new List<string[]>(); //csvファイルの中身を入れるリスト
public static int i = 0;
bool Auto;
public Text Nametext;
public Text Logtext;
public Image LeftImg;
public Image RightImg;
private AudioSource audio;
private AudioClip Sound;
public Button AutoBtn;
Startメソッドでは、CSVファイルの内容を読み込んでcsvDataリストに格納し、音声再生のためのAudioSourceコンポーネントを取得します。
Resources.Loadメソッドを使用して、「Data.csv」ファイルを読み込みます。
読み込んだファイルはTextAsset型の変数csvFileに格納します。
TextAsset型の変数csvFileのtextとして、CSVファイルの内容を文字列として取得します。
取得した文字列をStringReaderに渡し、StringReaderオブジェクトreaderを作成します。
StringReaderは、文字列を行単位で読み込むためのクラスです。
while文にて、reader.Peek()メソッドを使用して、次の文字が存在するかどうかを確認します。
Peekメソッドは、次の文字を読み込まずに取得します。
戻り値が-1でない場合、まだ読み込むべき行があることを意味します。
reader.ReadLine()メソッドを使用して、CSVファイルから1行分のデータを読み込みます。
読み込んだデータは、文字列変数lineに格納します。
line.Split(‘,’)を使用して、読み込んだ行の文字列をカンマで分割し、文字列配列として取得します。
取得した文字列配列をcsvDataリストに追加します。
GetComponent()メソッドを使用して、現在のゲームオブジェクトにアタッチされているAudioSourceコンポーネントを取得します。
取得したコンポーネントは、変数audioに格納します。
void Start()
{
//csvファイル
csvFile = Resources.Load("Data") as TextAsset; //Resourcesにあるcsvファイルを格納
StringReader reader = new StringReader(csvFile.text); //TextAssetをStringReaderに変換
while (reader.Peek() != -1)
{
string line = reader.ReadLine(); //1行ずつ読み込み
csvData.Add(line.Split(',')); //csvDataリストに追加
}
//音声を取得
audio = GetComponent<AudioSource>();
}
Updateメソッドでは、入力した時に、ユーザーの入力に対する処理を行います。
「EventSystem.current.IsPointerOverGameObject()」でUIボタンを押しても、画面押下判定がされないようにします。
「!Auto」は、「Auto == false」を意味しています。Autoがfalseのときに左押下すれば、Loadcsv()関数が読み込まれます。
対して、Autoがtrueで左押下した時、あるいは右クリックしたときはオート機能を停止して、UIボタンを元に戻します。
void Update()
{
//ボタンを押したときは画面クリック無効
if (EventSystem.current.IsPointerOverGameObject())
{
return;
}
//左クリックで Loadcsv();メソッドを読み込む
if (!Auto && Input.GetMouseButtonDown(0)) //!Autoは、左クリックでAuto解除するときに処理しないように
{
Loadcsv();
}
//Autoシステム解除
if (Input.GetMouseButtonDown(1) || Auto && Input.GetMouseButtonDown(0)) // 右クリックを検知
{
Auto = false; // 自動モード停止
AutoBtn.image.color = Color.white; // 色を元に戻す
Debug.Log("停止!" + "フラグ::::" + Auto);
}
}
Loadcsv()では、格納したcsvのデータを呼び起こします。
メソッドには、privateを使用して本スクリプト内からしか呼び起こせないようにしています。
このようにすることで、他スクリプトから干渉を受けずに処理することができます。
public、serializefieldとの違いが分からない場合は、以下の記事を読んでください。
//CSVを呼び出す(ローカルのみの処理)
private void Loadcsv()
{
Debug.Log("人物:" + csvData[i][0] + "セリフ:" + csvData[i][1]);
Nametext.text = csvData[i][0];
Logtext.text = csvData[i][1];
LeftImg.sprite = Resources.Load<Sprite>(csvData[i][2]);
RightImg.sprite = Resources.Load<Sprite>(csvData[i][3]);
//音声データ
Sound = (AudioClip)Resources.Load(csvData[i][4]);
audio.PlayOneShot(Sound);
if (i <= csvData.Count)
{
i++;
}
}
最後に、Auto機能を作成します。
Autobtnメソッドは、自動モードを開始するためのボタンがクリックされたときに呼び出されます。
Invokeメソッドを使用して、2秒後にAutomodeメソッドを呼び出します。
Autoをtrueに設定し、自動モードが開始されたことを示します。
ボタンの色をグレーに変更して、動作中であることを画面上で可視化します。
onclickでAutobtnをアタッチする必要があるので、Autobtnメソッドはprivateではなくpublicにしてください。
Automodeメソッドは、自動モードが有効な場合に周期的に呼び出されます。
Autoがfalseの場合、処理を中断して返ります。これにより、自動モードが解除された場合に処理が停止します。
Loadcsvメソッドを呼び出して、次のCSVデータを読み込みます。
AutoBtn.onClick.Invoke()を使用して、Autobtnメソッドを再度呼び出すことで、自動モードを連続して実行します。
//Autoシステム
public void Autobtn()
{
Invoke("Automode", 2.0f); //2秒後に"Automode"メソッドを読み込む
Auto = true;
Debug.Log("開始!" + "フラグ::::" + Auto);
AutoBtn.image.color = Color.gray; //ボタンの色をグレーにする。
}
//Invokeで使う
void Automode()
{
if (!Auto)
{
return; // Autoがfalseなら処理を中断
}
Loadcsv();
// Autobtnを押し続けるスクリプト
AutoBtn.onClick.Invoke();
}
}
実演
以下から動作確認ができます。
今回のスクリプト「csvcontroler.cs」をHierarchyウィンドウにアタッチをして、対応するUIをInspectorウィンドウにアタッチしてください。
前回からスクリプトにアタッチするUIを増やしていないので、そのままで大丈夫です。
また、AutoBtnを選択して、onclickの項目でAutobtn()メソッドをアタッチしてください。
ここまで完了しましたら、再生ボタンを押してください。
冒頭のような処理が行われば、成功です。
まとめ
ノベルゲームでオート機能を実装すると、テキストが自動的に表示され、一定の速度で自動的に進行します。
オートモードを導入すると、プレイヤーがわざわざクリック操作をせずにストーリーの流れやイベントの展開を自動的に楽しむことができます。
Unityで導入するには、Invokeを使い、引数を渡して数秒後に動作させます。