Unity キャラクターと会話する
■Topic
■方法
キャラクターを検出した際に
「立ち絵&メッセージウィンドウ」を表示する
▼完成イメージ
①Canvasを用意する
ものを表示するにはCanvasに置かないといけない。
まずは完成図通りになるようにいろいろなオブジェクトを配置していく
今回は以下のようにツリーを作った。
┗ScenarioManager(オブジェクト ここにスクリプトをあてて管理する)
┗Message(オブジェクト 以下、メッセージウィンドウセット)
┣Character(Image キャラの立ち絵)
┗MessageBox(Image メッセージウィンドウ)
┣Text(テキスト メッセージウィンドウに出す文字)
┗NamePlate(オブジェクト 管理用)
┣Back(Image 名前表示の背景ウィンドウ)
┗Text(テキスト 名前の文字)
ちなみに┣って罫線(けいせん)って入れると出るんですね
②ScenarioManagerにメッセージ管理用のスクリプトをあてる
Message以下の表示/非表示をスクリプトで管理したいので
以下のスクリプトを用意し、ScenarioManagerにアタッチする。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class ScenarioController : MonoBehaviour
{
//メッセージウィンドウのオブジェクトデータセット
public GameObject objMessage;//ボタンが押されたタイミングで同時に処理されるのを避けるため、
//boolでワンテンポ処理を遅らせる
public bool preMessageOpened = false;// Start is called before the first frame update
void Start()
{
}// Update is called once per frame
void Update()
{
//メッセージウィンドウが表示中かつ次がクローズの時
if(objMessage.activeSelf && !preMessageOpened)
{
objMessage.SetActive(false);
}
else if (!objMessage.activeSelf && preMessageOpened)
{
objMessage.SetActive(true);
}
else if (objMessage.activeSelf)
{
if (Input.GetKeyUp(KeyCode.Return))
{
//会話が終了したらclose
CloseMessage();
}
}
}//メッセージウィンドウをonにする
public void OpenMessage()
{
bool b = true;preMessageOpened = b;
}//メッセージウィンドウをoffにする
public void CloseMessage()
{
bool b = false;//会話が終了したらfalseに戻す
preMessageOpened = b;
}public bool GetPreMessageOpened()
{
return preMessageOpened;
}
}
設計としては、Message以下がActiveがtrueであるか、falseであるかで
表示状態/非表示状態を判断し、ボタンを押すことで切り替えを行う。
▼Activeの制御参考はこちら
【Unity入門】SetActiveで表示切り替え!よくある疑問も徹底解消! | 侍エンジニア塾ブログ(Samurai Blog) - プログラミング入門者向けサイト
③RayCastと紐づける
まだメッセージウィンドウの制御はあるものの、
RayCastとの紐づけがなされていないので、以下の処理を加える。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class RayCastTest : MonoBehaviour
{
public Camera camera_object; //カメラを取得//rayキャストが当たったものを取得する入れ物
public RaycastHit hit;//カーソルオブジェクト
public GameObject objCursor;//カーソルによって起動されるメッセージイベントオブジェクト
public GameObject objScenarioManager;//メッセージオブジェクト
public GameObject objMessage;void Update()
{
if (!objMessage.activeSelf)//会話状態でないなら
{
if (Input.GetKeyUp(KeyCode.Return))//Enterを押したら
{
//カーソルのポジションでrayを生成
Ray ray = Camera.main.ScreenPointToRay(objCursor.transform.position);//スクリーンに対するマウスのポジション
Debug.Log(Input.mousePosition);//マウスのポジションからRayを投げて何かに当たったらhitに入れる
if (Physics.Raycast(ray, out hit))
{
//オブジェクト名を取得して変数に入れる
string objectName = hit.collider.gameObject.name;//オブジェクト名をコンソールに表示
Debug.Log(objectName);switch (objectName)
{
case "Chr_01":
Debug.Log("なによ"); //オブジェクト名をコンソールに表示objScenarioManager.GetComponent<ScenarioController>().OpenMessage();
break;
case "Chr_02":
Debug.Log("やあ"); //オブジェクト名をコンソールに表示
break;default:
Debug.Log("何もないようだ"); //オブジェクト名をコンソールに表示
break;
}
}
}
}
}
}
スクリプトをアタッチしたら、
それぞれの欄にオブジェクト(ScenarioManager、Message)を紐づける
④会話中はカーソルが動かないようにする
今のままだと話している裏でカーソルが動かせてしまうので、
そちらも処理を入れる。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class CursorController : MonoBehaviour
{
public float cursorSpeed = 0.1f;//メッセージオブジェクト
public GameObject objMessage;// Start is called before the first frame update
void Start()
{
}// Update is called once per frame
void Update()
{
if (!objMessage.activeSelf)
{
// 左に移動
if (Input.GetKey(KeyCode.LeftArrow))
{
this.transform.Translate(-cursorSpeed, 0.0f, 0.0f);
}
// 右に移動
if (Input.GetKey(KeyCode.RightArrow))
{
this.transform.Translate(cursorSpeed, 0.0f, 0.0f);
}
// 上に移動
if (Input.GetKey(KeyCode.UpArrow))
{
this.transform.Translate(0.0f, cursorSpeed, 0.0f);
}
// 下に移動
if (Input.GetKey(KeyCode.DownArrow))
{
this.transform.Translate(0.0f, -cursorSpeed, 0.0f);
}
}
}
}
何のことはなく、メッセージが出ていたらカーソルが動かせない
というだけのもの。
これによって、「カーソルで選択すると立ち絵とセリフが出る」
「セリフを送ると画面が閉じる」が達成された。
だんだんややこしくなってきた…