街を探索して住人と会話する場面をUnityで実装してみました。会話機能自体は、「宴」など簡単に実装できるソフトがあるらしいですが、今回はスクリプトだけで実装してみます。
全体の流れとしては
1.住人の設置
2.住人の喋る内容を設定するスクリプト
3.テキストを表示するスクリプト
4.プレイヤーが一定範囲内に入ったら会話できるサインを表すオブジェクトの表示設定
の順番で説明していきたいと思います。
ちなみに完成イメージはこんな感じです。今回はこの画像の中の、Aボタンと水色のテキストウィンドウの機能について説明します。
##1.住人の設置
まずは街の住人とプレイヤーを設置します。
プレイヤーの移動や配置などは割愛しますが、今回は住人とプレイヤーの両方にColliderをつけましょう。そして、住人側のColliderにはisTriggerにチェックを入れます。参考までに、プレイヤーと住人のColliderの適用範囲の画像を載せます。適用範囲とは、要するに会話可能範囲です。加えて、プレイヤーにはRigidBodyと"player"と言う名前でタグをつけておきましょう。
今回はプレイヤーと住人はリンク先の素材を使いました。ここは自由に変更してください。
##2.住人の喋る内容を設定するスクリプト
下のCharacterScriptを作成して、住人につけます。
前述したようにプレイヤーにはあらかじめ、playerという名前でタグをつけて起きましょう。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class CharacterScript : MonoBehaviour {
//住人の話す内容
public string[] scenarios;
//プレイヤーが一定範囲内に入ったら会話できるサインを表すオブジェクト
public GameObject heart;
//プレイヤーが範囲内にいるかどうかの判定
bool Aflagflag = false;
public IventScript iventScript;
void Start () {
heart.SetActive (false);
}
void Update () {
}
void OnTriggerEnter(Collider other){
//もしplayerタグをつけたゲームオブジェクトが住人のCollider判定範囲に入ったら
if (other.gameObject.tag == "player") {
Aflagflag = true;
//IventScriptのStartIventメソッドに会話が可能な状態であることを示すフラグと、住人の話す内容を送る。
iventScript.StartIvent (Aflagflag, scenarios);
//住人の頭上にオブジェクトを表示(座標は自由に変えてください)
heart.transform.position = gameObject.transform.position + new Vector3 (-0.5f, 1f, 0);
heart.SetActive (true);
}
}
void OnTriggerExit(Collider other){
if(other.gameObject.tag=="player"){
//プレイヤーが範囲外に出たら会話しない。
Aflagflag = false;
heart.SetActive (false);
}
}
}
スクリプトの説明をします。
プレイヤーが住人のCollider範囲=会話可能な範囲内に入ったら、Aflagflagをtrueにし、iventScriptに、セリフの内容とAflagflagの結果を送ります。そして、プレイヤーに会話が可能だと知らせるために用意したheartというオブジェクトを住人の頭上に表示します(iventScriptについてはこの後に説明します)
プレイヤーが会話可能な範囲外に出たら、Aflagflagをfalseにし、heartを消します。
先ほど用意した住人にこのスクリプトをアタッチして見ましょう。そうすると、住人のインスペクタービューにCharacterScriptが表示されます。ここのScenariosの部分でシナリオの長さ(Size)と喋る内容を設定できます。
HeartIconとIventControllerについてはこの後説明しますので、完成したら忘れずにここにアタッチしておきましょう。
次にIventScriptについて説明します。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class IventScript : MonoBehaviour {
public TextController textController;
//CharacterScriptから送られてきたAflagflagの格納用
bool flag2=false;
//CharacterScriptから送られてきたscenariosの格納用
string[] scenarios2;
public void StartIvent (bool flag,string[] scenarios) {
flag2 = flag;
scenarios2 = scenarios;
}
void Update () {
}
public void AButton(){
if (flag2) {
textController.StartText (scenarios2);
flag2 = false;
}
}
}
今回は、プレイヤーが住人に近づいて、ボタンを押したら会話をするように実装します。
そのため、Canvasにあらかじめそれ用のボタン(ここではAボタン)を用意し、AButtonメソッドをClickの部分にアタッチしてください。
そうすると、プレイヤーが会話可能な範囲内にいて、かつ、ボタンを押したら会話イベントが発生する仕組みになります。
また、空のゲームオブジェクトを用意して、名前をIventControllerとします。そして、そこにIventScriptをアタッチしましょう。
〜会話をするためのボタン(Aボタン)のインスペクタービュー〜
〜IventController(空のゲームオブジェクト)のインスペクタービュー〜
##3.テキストを表示するスクリプト
次に、住人の話す内容を表示するためのTextControllerスクリプトを用意します。このスクリプトはこちらのサイト様のを参考にしました。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class TextController : MonoBehaviour {
//シナリオを格納
private string[] scenarios2;
//uiTextへの参照を保つ
private Text uiText;
//現在の行番号
int currentLine;
//セリフを表示するテクスト(文字の大きさや色はここにアタッチしたTextをいじって決定する)
public Text message;
int flag=0;
//テキストウィンドウ
public GameObject panel;
// Use this for initialization
public void StartText (string[] scenarios) {
flag=1;
scenarios2=scenarios;
currentLine = 0;
uiText = message;
//パネルを表示
panel.SetActive (true);
//テクストを表示
uiText.gameObject.SetActive (true);
TextUpdate ();
}
public void Click(){
if (flag == 1) {
//現在の行番号がラストまで行ってない状態でボタンを押すとテキストを更新する
if (currentLine < scenarios2.Length) {
TextUpdate ();
} else {
//最後まで行ったら、テキストとテキストウィンドウを消す
uiText.gameObject.SetActive (false);
panel.SetActive (false);
flag = 0;
}
}
}
void TextUpdate(){
//現在の行番号をuiTextに流し込み、現在の行番号を一つ追加する
uiText.text = scenarios2 [currentLine];
currentLine++;
}
}
ヒエラルキービューに空のゲームオブジェクトを用意して、名前をTextControllerとし、このスクリプトをアタッチしましょう。
〜TextController(空のゲームオブジェクト)のインスペクタービュー〜
そして、Canvas内にテキストウィンドウとなるPanelとセリフを表示する用のTextを作成します。TextはPanelの子オブジェクトにしましょう。以下の画像を参考にして見てください。
上記のパネルや文字のスタイルはあくまで参考程度なのでお好きな形に変えてください。作ったPanelとTextはTextControllerのインスペクタービューにアタッチしましょう。
また、前述したIventControllerとボタンのOnClickの部分にTextCOntrollerをアタッチしましょう。
##4.プレイヤーが一定範囲内に入ったら会話できるサインを表すオブジェクトの表示設定
ここまでで会話機能は成立しますが、今の状態だとどのタイミングで会話可能なのかが分かりません。なので次は、プレイヤーが会話可能な範囲に入ったら、住人の頭上にハートのオブジェクトを表示して、ボタンを押したら会話が可能だと知らせるようにしましょう。
ここまでくれば後は簡単です。
オブジェクトはなんでも良いです。私は、カプセルを二つくっつけたハート?のオブジェクトを用意しました。
CharacterScriptの様々な部分でpublic GameObject heartやheart.SetActive (true)といった表記を目にしたと思います。CharacterScriptにハートのオブジェクトを住民の頭上に表示するための命令は書いてあるので、後はそのCharacterScriptをつけた住人のインスペクタービューにこのHeartIconオブジェクトをアタッチするだけです。
説明は以上です。お疲れ様でした!