バーチャル3Dクリエイター神部まゆみです(*^_^*)
この記事はUnityで会話システムを作ってみた記事の続きです。
前回の記事はこちら。
動作確認した最新のバージョンはUnity6000.0.32です。
やりたいこと:会話ボタンを押したらゲーム画面を一時停止、半透明の会話ウィンドウと顔グラフィックを表示する
まぁ一般的な会話システムみたいな感じですね。
顔グラフィックの表情を切り替えたりもしたいけど、とりあえず今回はそこまでやらないっす。
実装して行ってみる
前回に続いて進めていきます。
顔グラフィックを用意する
クロマキー背景にすると透過させやすいです。
GIMPで「色で透明化」をつかうとできるけど、確か透過させるサイトとかあったっけな?まぁGIMPで使い慣れてるのでこれで。
レイヤー ⇒ 透明部分 ⇒ 色を透明度に で、 スポイトで色を指定、Opacity thresholdの値を下げて保存すればOK。
保存した画像をAssetフォルダに放り込んで、テクスチャタイプを スプライト(2DとUI)に、 スプライトモード を 単数 に。この設定しないと使えないので注意。


DialogueManager.csを用意してセットする
前回の記事で用意したけど一応ここにも書いておく。
using UnityEngine;
using UnityEngine.UI;
using System.Collections.Generic;
public class DialogueManager : MonoBehaviour
{
public GameObject dialogueCanvas; // 会話用キャンバス
public Text villagerDialogueText; // 村人のセリフ用テキストUI
public Text playerDialogueText; // プレイヤーのセリフ用テキストUI
private Queue<string> sentences; // セリフをキューで管理
private bool isTalking = false; // 会話中かどうかを管理
private bool isVillagerSpeaking = true; // 交互に話すためのフラグ
void Start()
{
sentences = new Queue<string>();
}
public void StartDialogue()
{
if (isTalking) return;
isTalking = true;
Time.timeScale = 0; // ゲームを一時停止
// 会話用キャンバスを表示
dialogueCanvas.SetActive(true);
sentences.Clear();
sentences.Enqueue("こんにちは!村へようこそ!"); // 村人
sentences.Enqueue("よろしくお願いします!"); // プレイヤー
sentences.Enqueue("この村にはたくさんの人がいますよ。"); // 村人
sentences.Enqueue("楽しみです!"); // プレイヤー
DisplayNextSentence();
}
public void DisplayNextSentence()
{
if (sentences.Count == 0)
{
EndDialogue();
return;
}
// 交互にセリフを表示(村人とプレイヤー)
if (isVillagerSpeaking)
{
villagerDialogueText.gameObject.SetActive(true); // 村人のテキストUIを表示
playerDialogueText.gameObject.SetActive(false); // プレイヤーのテキストUIを非表示
villagerDialogueText.text = sentences.Dequeue(); // 村人のセリフをセット
}
else
{
villagerDialogueText.gameObject.SetActive(false); // 村人のテキストUIを非表示
playerDialogueText.gameObject.SetActive(true); // プレイヤーのテキストUIを表示
playerDialogueText.text = sentences.Dequeue(); // プレイヤーのセリフをセット
}
isVillagerSpeaking = !isVillagerSpeaking;
}
public void EndDialogue()
{
// 会話終了後にキャンバスを非表示にする
dialogueCanvas.SetActive(false);
Time.timeScale = 1; // ゲーム再開
isTalking = false;
}
void Update()
{
if (isTalking && Input.GetKeyDown(KeyCode.Return)) // Enterキーで次の文章へ
{
DisplayNextSentence();
}
}
}
これはこの村人との会話なので村人にセットしておけばいいか。
あとで一括で管理するシステムとか作ってみるかもしれないけど、今回はこれで。
キャンバス、パネル×2とテキスト×2と画像×2を追加する
キャンバスの子にパネル×2、テキスト×2、画像×2を追加して名前を付けます。
テキストは今回は古い機能のヤツ(テキストメッシュプロではない)でやります。


↓名前と親子構造はこんな感じ。


TalkWindows キャンバス
PlayerPanel プレイヤーの会話ウィンドウになるパネル
VillagerPanel 村人の会話ウィンドウになるパネル
Player プレイヤーの画像
Villager 村人の画像
VillagerText 村人の会話を表示するテキスト
PlayerText プレイヤーの会話を表示するテキスト
位置を揃える
ゲーム画面に行ってUIの位置を揃えます。
とりあえず上に村人の画像とパネル、下にプレイヤーの画像とパネルを置けばいいかな。
まぁこんな感じで配置するとそれっぽくなると思うのだけど。
名前も表示しといた方が分かりやすいかな…?
まぁ後でやってみるかもしれない。
テキストがちゃんと折り返すように調整したほうが良いかも
多めに文字数を入れてみて、高さや幅、位置などを調整しておくと長文でもちゃんと折り返してくれます。


追加したUIをDialogueManagerで設定
村人に追加したDialogueManagerの設定をします。
DialogueCanvasにはキャンバスを、Villager Dialogue Textには村人のテキスト、Player Dialogue Textにはプレイヤーのテキストを設定します。


キャンバスは非表示にしておく
話すモードになったら表示するのでインスペクターで非表示にしておきます。


あとでスクリプトで非表示にするように改良しておくかもしれない。
これで動いた!
おお!だいたいイメージ通り。
つづく
案外簡単にできて良かった。
しかしこれだと村人ごとにスクリプトを用意して会話部分を変えないといけないのでちょっと大変かな(^_^;)
ChatGPT氏がいうには、なんとかObjectとかいう機能を使えばテキストを格納して管理できるっぽい?
まぁ次回やってみようかな。
これで会話システムがちゃんと作れるようになれば、一気にストーリー性が出てきてゲームとして面白くなりそう。
私もこういう3Dゲームってよくやるけど、まぁ規模の大小はあれどだいたいミッション形式のお使いゲームみたいなのが多いから、会話とミッションを増やせばそれだけでまぁ遊べるものになる気がする。
もう少しいじってみます(*^_^*)
追記:続きを書きました。