UEを学ぶ「タイトル画面を作る_2 特定のボタンでのみ遷移する」

Q&Aで触れられている内容について

それぞれ拾っていきます

 

youtu.be

 

■特定のボタンで遷移されるようにする

 

AnyKeyだと、すべてのボタンで遷移するが

実際はそうしたくない場合が多いので

特定のボタン(例だとスタートボタン)でのみ遷移を行うようにする。

 

方法は2つ紹介されていて、

1つはgamepadでノードを検索すると出てくるボタンの候補から

好きなノードを選んでAnyKeyと同じようにノードを接続する。

f:id:happyherpy:20211025015335p:plain

f:id:happyherpy:20211025015535p:plain

もう1つは、Keyに条件をせっていすること。

操作として、

いずれかのキー の Key部分からドラッグでノードを伸ばし

検索窓に「equal」の文字を入力することで、

「特定のキーに等しいとき」という条件を

Keyに与えることができる。

(動画中では何か記号を打ち込んでいたが、再現できないのでequalでいいと思う)

 

さらに、出てきたequalのプルダウンから

ゲームパッド>特別仕様の右

を選択する。

これによって、自分の環境ではゲームパッドのSTARTボタンでのみ

ゲームを開始することができる。

 

ただしそのままではOpenLevelに接続できないので

ブランチ(分岐)ノードを作って

Conditionにつなげてあげる必要がある。

(ちなみに Bキー+左クリック でブランチを作ることができる)

UE4 ショートカットキーなどの便利操作(BP編) 凛(kagring)のUE4/UE5とUnityとQt勉強中のゲーム制作ブログ

f:id:happyherpy:20211025013201p:plain

 

これによって

「いずれかのキーが押されたとき、

そのキーがSTARTボタンだった場合、OpenLevelする」

というプログラムの塊になれる。

※Releasedだと離れた時。状況によって使い分けよう

※ちなみに、同様の手順でequalを増やしていくと、以前のKeyのつながりは切れてしまった。

 同時に一つしか繋げられないようだ。

 

False側にもSEなどを繋げてあげれば、何かしらの処理を行えるだろう

UEを学ぶ「タイトル画面を作る」

以下の動画を参考にUEを習得していきます。

 

youtu.be

 

動画がとても長いのでちょっとずつ

備忘録としてまとめていきます。

 

---

 

【タイトル画面を作る】

 

動画内での進め方は以下の通り

 

  1. 新しいレベル「Title」をつける
    右クリックからメニューを開き「レベル」を選択する。

    f:id:happyherpy:20211021003801p:plain

    レベル

    作成されたNewMapに「Title」と付ける。

    これでタイトル画面のタネが完成。
    ※動画中では
     ファイル>新規レベル>TimeOfDay
     のサンプルを使用していたのでそちらに合わせたほうが良い。

    このとき、レベル内の
    Title(エディタ)>GameMode>ゲームモードオーバーライド
    がNoneになっているとプロジェクト設定で設定されたゲームモードを勝手に読んでしまうとのこと。
    動画内では「BP_MyGameMode」という新しいゲームモードを作って対応していた。

    ゲームモードの作り方はコンテンツブラウザ上で
    右クリック>ブループリントクラス>GameModeBase
    を選択する

    f:id:happyherpy:20211021004754p:plain

    ゲームモード

    作成したゲームモードを先ほどのNoneになっていた
    ゲームモードオーバーライドに設定します。
    ※画像中の背景は動画と同じくテンプレートのものを使用

    f:id:happyherpy:20211021005220p:plain

    ゲームモードを設定
    そのあとゲームモードの設定のDefaultPawnをごそごそいじっていますが、
    正直よくわからないです。

  2. 画面に文字を表示する
    画面に文字を表示するにはユーザーインターフェース
    追加する必要があるそうです。
    コンテンツブラウザ上で
    右クリック>ユーザーインターフェース(一番下)>ウィジェットブループリント
    を選択してUIを追加。ファイル名はUMG_Title。

    f:id:happyherpy:20211021010937p:plain


    追加したUMG_Titleをダブルクリックで開くと
    キャンパスが現れるので
    画面左のパレットから「TextBox」をドラッグして画面内に追加する。

    f:id:happyherpy:20211021011110p:plain

    TextBoxの文字入力欄に「クレイマンの冒険」
    もう一つ追加して「PressAnyButton」と入力する。
    入力した後は画面右の詳細から
    スロット>SizeToContentにチェックを入れること。
    これでTextBoxのサイズが自動的に文字の幅に合わさる。
    文字の大きさは
    詳細>アピアランス>Font>Size
    を設定することで自由に変更可能。
    また
    詳細>スロット>アンカー
    のプルダウンをクリックすると、アンカーの位置を設定できる。
    動画内では「画面中央上部」に合わせる設定をしていたので
    よくわからないが設定する。
    ちなみにTextBoxはCtrl+ドラッグで移動可能。
    ただ、毎回詳細の選択状況が外れるのはやめてほしい。
    (何かいい方法があるのだろうか?)

  3. ボタンを押したらタイトルから遷移する仕組みを作る
    画面上部から
    ブループリント>レベルブループリントを拓く
    を選択して、プログラム設定を行っていく。

    手始めに、画面上に文字を表示する仕組みを作る。
    右クリックからcreate widgetと入力することで
    ウィジェットを作成」を見つけ出し、配置。
    BeginPlayとつなげることで、先ほど作ったUIを読み込む。
    更に「AddToViewport」を追加し、それを画面上に追加する。
    これで文字の表示が可能に。

    f:id:happyherpy:20211021014007p:plain


    更にボタンを押したら、画面が遷移する仕組みを作る。
    右クリックで「Any Key」と入力すると「いずれかのキー」というノードが選べるので配置。
    更に「OpenLevel」と検索して配置し、それらをつなぎ合わせる。
    ※画像上のPrintStringは動画内で機能説明時に作成されたもの

    f:id:happyherpy:20211021014913p:plain

    OpenLevelの引数(LevelName)に開きたいレベルの名前を入れると
    画面上でいずれかのキーを入力したときに、
    該当のレベルへ遷移するようになる。

    ただし、同じ名前のレベルが複数存在する場合、どれが開かれるのか制御できないため
    レベルを右クリック>リファレンスをコピー
    して、LevelNameに設定することで、特定のレベルを指定することができる。
    ※この時「World' '」と最初と最後で閉じられているが、
     これは不要な文字なので消す必要がある。
     (つけたままだと真っ暗な画面に飛ばされました)

    ここまで行うと、タイトル画面とそこからの遷移ができたことになる

    ここまで動画の~30分ほど。
    次は合間にあったフェードイン/アウト処理やキー操作をまとめる

Unity キャラクターと会話する

■Topic

ダンガンロンパみたいに検出したキャラクターに話しかけたい

 

■方法

キャラクターを検出した際に

「立ち絵&メッセージウィンドウ」を表示する

 

▼完成イメージ

f:id:happyherpy:20200927005015p:plain

 

Canvasを用意する

ものを表示するにはCanvasに置かないといけない。

まずは完成図通りになるようにいろいろなオブジェクトを配置していく

 

今回は以下のようにツリーを作った。

Canvas

┗ScenarioManager(オブジェクト ここにスクリプトをあてて管理する)

 ┗Message(オブジェクト 以下、メッセージウィンドウセット)

  ┣Character(Image キャラの立ち絵)

  ┗MessageBox(Image メッセージウィンドウ)

   ┣Text(テキスト メッセージウィンドウに出す文字)

   ┗NamePlate(オブジェクト 管理用)

    ┣Back(Image 名前表示の背景ウィンドウ)

    ┗Text(テキスト 名前の文字)

 

f:id:happyherpy:20200927010414p:plain

ちなみに┣って罫線(けいせん)って入れると出るんですね

「├」や「└」などの罫線を入力するには?

 

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)を紐づける

f:id:happyherpy:20200927020921p:plain

④会話中はカーソルが動かないようにする

今のままだと話している裏でカーソルが動かせてしまうので、

そちらも処理を入れる。

 

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);
}
}
}
}

何のことはなく、メッセージが出ていたらカーソルが動かせない

というだけのもの。

 

これによって、「カーソルで選択すると立ち絵とセリフが出る」

「セリフを送ると画面が閉じる」が達成された。

だんだんややこしくなってきた…

f:id:happyherpy:20200927005015p:plain

 

Unity カーソルの座標を元にRayを生成する

■Topic

ダンガンロンパみたいにカーソルを動かしてオブジェクトを検出したい。

(マウスで検出するのではなく)

 

■方法

「カーソルが動かせる」+「カーソルの座標を元にRayを生成する」

この2つを順番に実装する必要がある。

どちらもやろうとすると頭がいっぱいになるので注意。

 

▼完成イメージ

f:id:happyherpy:20200916015503p:plain

 

①カーソルを画面に表示する

何はともあれ、カーソルが画面に出ていないことには話が始まらない。

いろいろと悩んだが、何がいいかわからなかったので

結局UIとして表示することにした。

 

Hierarchyで右クリック > UI > Image

と選択していき、CanvasやらEventSystemと一緒にImageを生成される。

(わかりやすくCursorと命名

Imageに画像を設定することで、カーソルが表示されるようになる。

 

f:id:happyherpy:20200916021809p:plain

 

②カーソルを動かせるようにプログラムを作る

画像を置いただけではカーソルを操作できない。

コードでカーソルが動くようにしてやる必要がある。

 

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

public class CursorController : MonoBehaviour
{
public float cursorSpeed = 0.1f;

// Start is called before the first frame update
void Start()
{

}

// Update is called once per frame
void Update()
{
// 左に移動
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);
}
}
}

 ▼参考にしたページ

【Unity】キー入力入門!超簡単なInputクラスの使い方! | 侍エンジニア塾ブログ(Samurai Blog) - プログラミング入門者向けサイト

 ※本コードではX,Yの2次元で動くため、

 X,Yにそれぞれ入力に応じた方向へSpeedで移動する。

 終わったらCursorのInspectorに乗っけてアタッチ。

f:id:happyherpy:20200916023904p:plain

③カーソルの位置からRayを生成する

前回作った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;

void Update()
{
if (Input.GetKeyUp(KeyCode.Return))//Enterを押したら
{
//マウスのポジションでrayを生成
Ray ray = Camera.main.ScreenPointToRay(objCursor.transform.position);
Debug.Log(Input.mousePosition); //スクリーンに対するマウスのポジション

if (Physics.Raycast(ray, out hit))
//マウスのポジションからRayを投げて何かに当たったらhitに入れる
{
string objectName = hit.collider.gameObject.name; //オブジェクト名を取得して変数に入れる

Debug.Log(objectName); //オブジェクト名をコンソールに表示

switch (objectName)
{
case "Chr_01":
Debug.Log("なによ"); //オブジェクト名をコンソールに表示
break;
case "Chr_02":
Debug.Log("やあ"); //オブジェクト名をコンソールに表示
break;

default:
Debug.Log("何もないようだ"); //オブジェクト名をコンソールに表示
break;
}
}
}
}
}

単純なGetKeyだと押している間検出し続けてしまうので、

GetKeyUpで離した瞬間のみに修正。

入力はカーソルオブジェクトをpublicで紐づけして、

そこのVector3座標であるtransform.positionを取得して放り込む。

シンプルすぎて不安だったが、なんとかなった。

▼参考にしたサイト

UnityのInputで入力を扱う - Qiita

 

f:id:happyherpy:20200916023401p:plain

 

というわけで実装完了。

悩んだ割に作るのはすぐである。

Unity RayCastでキャラクターを検出する

■Topic

ダンガンロンパみたいにアドベンチャーっぽい感じで

対象を検出したい

 

■方法

一般的に広く伝わるRayCastを使わせていただき、

「画像をクリックするとひとまずセリフがデバッグ表示される」

を目指す。

▼完成イメージ

f:id:happyherpy:20200914013121p:plain

①RayCastオブジェクトを作る

何はともあれRayCastオブジェクトがないといけないので、

Hierarchy上で

右クリック > Create Empty

でからのオブジェクトを作成。

名前をRayCastとする。

 

f:id:happyherpy:20200914013707p:plain

②Scriptを作る

 最下部のリンクの内容を組み合わせたため、

コピペ率が高いが、動くものを目指していく。

ちなみにcaseの内容は検出するオブジェクト名と揃える必要があります。

 

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

public class RayCastTest : MonoBehaviour
{
public Camera camera_object; //カメラを取得

//rayキャストが当たったものを取得する入れ物
public RaycastHit hit;

void Update()
{
if (Input.GetMouseButtonDown(0)) //マウスがクリックされたら
{
//マウスのポジションでrayを生成
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);

if (Physics.Raycast(ray, out hit))
//マウスのポジションからRayを投げて何かに当たったらhitに入れる
{
string objectName = hit.collider.gameObject.name; //オブジェクト名を取得して変数に入れる

Debug.Log(objectName); //オブジェクト名をコンソールに表示

switch (objectName)
{

case "Chr_01":
Debug.Log("なによ"); //女の子セリフをコンソールに表示
break;
case "Chr_02":
Debug.Log("やあ"); //男の子セリフをコンソールに表示
break;

default:
Debug.Log("何もないようだ"); //オブジェクト名をコンソールに表示
break;
}
}
}
}
}

 ③カメラを入れて終わり

スクリプトを入れてコンパイルが通れば、

camera_object

にメインカメラを入れることができるので、

それを行ってゲームを実行すればセリフが再生されるはずです。

 

f:id:happyherpy:20200914014608p:plain

 

--- 

■参考にさせて頂いた記事

RayCastその4、Raycastを2Dで使う【Unity】 - (:3[kanのメモ帳]

マウスでクリックしたオブジェクトの情報を取得する - Qiita

【Unity】FPS系ゲーム制作に使えるraycastの使い方(3D・2D) – XR-Hub

Unity 2D画像を3D空間上に表示したい

■Topic

ダンガンロンパみたいに3D空間上に2Dキャラクターを表示したい。

 

が、意外と検索に苦労した。

 

■方法

▼目指す状況

f:id:happyherpy:20200913230254p:plain

①3D空間に板を置く

Unityの3D空間上に、まずはキャンバスとなる板を作ります。

 

Hierarchy > 3DObject > Quad で立ち絵っぽい感じになる板が作れます。

※Planeで作るとXZ方向(床)に板が作られるので床を作りたい場合はそちら。

 

f:id:happyherpy:20200913231448p:plain

②マテリアルを作る

3Dの板に画像を貼るためには、マテリアルを作る必要がある。

Projectタブ内に適当に

右クリック > create > Material

でマテリアルを作成する。

 

f:id:happyherpy:20200913231833p:plain

③マテリアルのShaderを設定する

そのまま貼っても透過が反映されなかったりして

思ったように表示されないので、

Shaderを設定する必要がある。

(この設定を調べるのにとても時間がとられた・・・)

 

Inspector > Shaderからプルダウンを見る > Unlit > Transparent

でShaderを設定する。

 

f:id:happyherpy:20200913232906p:plain

④画像を設定する

Selectから使いたい画像を設定する。

枠に画像を放り込んでもいいし、

Selectをクリックして適当に選んでもいい。

f:id:happyherpy:20200913234914p:plain

⑤マテリアルをオブジェクトに適用して画像を表示する

オブジェクトに作ったマテリアルを適用します。

オブジェクトにドラッグしてもいいし、

Inspector > Element01 から選択してもいい

表示自体はこれで完了ですが、矩形に沿った形になって不本意です。

 

f:id:happyherpy:20200914000504p:plain

⑥Scaleで形を調節する

 悲しいことにデブっとした画像は

Scaleをいじって形を整えていくしかないっぽいです。

(対抗策あれば更新します…) 

 

画像は事前に比率を決めておき、

スケールを一律で調整できるようにしておきましょう。

 

---

 

■参考にさせて頂いた記事

< Unity >透過処理した画像について - なんでもログ