UEを学ぶ「タイトル画面を作る_2 特定のボタンでのみ遷移する」
Q&Aで触れられている内容について
それぞれ拾っていきます
■特定のボタンで遷移されるようにする
AnyKeyだと、すべてのボタンで遷移するが
実際はそうしたくない場合が多いので
特定のボタン(例だとスタートボタン)でのみ遷移を行うようにする。
方法は2つ紹介されていて、
1つはgamepadでノードを検索すると出てくるボタンの候補から
好きなノードを選んでAnyKeyと同じようにノードを接続する。
もう1つは、Keyに条件をせっていすること。
操作として、
いずれかのキー の Key部分からドラッグでノードを伸ばし
検索窓に「equal」の文字を入力することで、
「特定のキーに等しいとき」という条件を
Keyに与えることができる。
(動画中では何か記号を打ち込んでいたが、再現できないのでequalでいいと思う)
さらに、出てきたequalのプルダウンから
ゲームパッド>特別仕様の右
を選択する。
これによって、自分の環境ではゲームパッドのSTARTボタンでのみ
ゲームを開始することができる。
ただしそのままではOpenLevelに接続できないので
ブランチ(分岐)ノードを作って
Conditionにつなげてあげる必要がある。
(ちなみに Bキー+左クリック でブランチを作ることができる)
UE4 ショートカットキーなどの便利操作(BP編) 凛(kagring)のUE4/UE5とUnityとQt勉強中のゲーム制作ブログ
これによって
「いずれかのキーが押されたとき、
そのキーがSTARTボタンだった場合、OpenLevelする」
というプログラムの塊になれる。
※Releasedだと離れた時。状況によって使い分けよう
※ちなみに、同様の手順でequalを増やしていくと、以前のKeyのつながりは切れてしまった。
同時に一つしか繋げられないようだ。
False側にもSEなどを繋げてあげれば、何かしらの処理を行えるだろう
UEを学ぶ「タイトル画面を作る」
以下の動画を参考にUEを習得していきます。
動画がとても長いのでちょっとずつ
備忘録としてまとめていきます。
---
【タイトル画面を作る】
動画内での進め方は以下の通り
- 新しいレベル「Title」をつける
右クリックからメニューを開き「レベル」を選択する。
作成されたNewMapに「Title」と付ける。
これでタイトル画面のタネが完成。
※動画中では
ファイル>新規レベル>TimeOfDay
のサンプルを使用していたのでそちらに合わせたほうが良い。
このとき、レベル内の
Title(エディタ)>GameMode>ゲームモードオーバーライド
がNoneになっているとプロジェクト設定で設定されたゲームモードを勝手に読んでしまうとのこと。
動画内では「BP_MyGameMode」という新しいゲームモードを作って対応していた。
ゲームモードの作り方はコンテンツブラウザ上で
右クリック>ブループリントクラス>GameModeBase
を選択する
作成したゲームモードを先ほどのNoneになっていた
ゲームモードオーバーライドに設定します。
※画像中の背景は動画と同じくテンプレートのものを使用
そのあとゲームモードの設定のDefaultPawnをごそごそいじっていますが、
正直よくわからないです。 - 画面に文字を表示する
画面に文字を表示するにはユーザーインターフェースを
追加する必要があるそうです。
コンテンツブラウザ上で
右クリック>ユーザーインターフェース(一番下)>ウィジェットブループリント
を選択してUIを追加。ファイル名はUMG_Title。
追加したUMG_Titleをダブルクリックで開くと
キャンパスが現れるので
画面左のパレットから「TextBox」をドラッグして画面内に追加する。
TextBoxの文字入力欄に「クレイマンの冒険」
もう一つ追加して「PressAnyButton」と入力する。
入力した後は画面右の詳細から
スロット>SizeToContentにチェックを入れること。
これでTextBoxのサイズが自動的に文字の幅に合わさる。
文字の大きさは
詳細>アピアランス>Font>Size
を設定することで自由に変更可能。
また
詳細>スロット>アンカー
のプルダウンをクリックすると、アンカーの位置を設定できる。
動画内では「画面中央上部」に合わせる設定をしていたので
よくわからないが設定する。
ちなみにTextBoxはCtrl+ドラッグで移動可能。
ただ、毎回詳細の選択状況が外れるのはやめてほしい。
(何かいい方法があるのだろうか?) - ボタンを押したらタイトルから遷移する仕組みを作る
画面上部から
ブループリント>レベルブループリントを拓く
を選択して、プログラム設定を行っていく。
手始めに、画面上に文字を表示する仕組みを作る。
右クリックからcreate widgetと入力することで
「ウィジェットを作成」を見つけ出し、配置。
BeginPlayとつなげることで、先ほど作ったUIを読み込む。
更に「AddToViewport」を追加し、それを画面上に追加する。
これで文字の表示が可能に。
更にボタンを押したら、画面が遷移する仕組みを作る。
右クリックで「Any Key」と入力すると「いずれかのキー」というノードが選べるので配置。
更に「OpenLevel」と検索して配置し、それらをつなぎ合わせる。
※画像上のPrintStringは動画内で機能説明時に作成されたもの
OpenLevelの引数(LevelName)に開きたいレベルの名前を入れると
画面上でいずれかのキーを入力したときに、
該当のレベルへ遷移するようになる。
ただし、同じ名前のレベルが複数存在する場合、どれが開かれるのか制御できないため
レベルを右クリック>リファレンスをコピー
して、LevelNameに設定することで、特定のレベルを指定することができる。
※この時「World' '」と最初と最後で閉じられているが、
これは不要な文字なので消す必要がある。
(つけたままだと真っ暗な画面に飛ばされました)
ここまで行うと、タイトル画面とそこからの遷移ができたことになる
ここまで動画の~30分ほど。
次は合間にあったフェードイン/アウト処理やキー操作をまとめる
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);
}
}
}
}
何のことはなく、メッセージが出ていたらカーソルが動かせない
というだけのもの。
これによって、「カーソルで選択すると立ち絵とセリフが出る」
「セリフを送ると画面が閉じる」が達成された。
だんだんややこしくなってきた…
Unity カーソルの座標を元にRayを生成する
■Topic
ダンガンロンパみたいにカーソルを動かしてオブジェクトを検出したい。
(マウスで検出するのではなく)
■方法
「カーソルが動かせる」+「カーソルの座標を元にRayを生成する」
この2つを順番に実装する必要がある。
どちらもやろうとすると頭がいっぱいになるので注意。
▼完成イメージ
①カーソルを画面に表示する
何はともあれ、カーソルが画面に出ていないことには話が始まらない。
いろいろと悩んだが、何がいいかわからなかったので
結局UIとして表示することにした。
Hierarchyで右クリック > UI > Image
と選択していき、CanvasやらEventSystemと一緒にImageを生成される。
(わかりやすくCursorと命名)
Imageに画像を設定することで、カーソルが表示されるようになる。
②カーソルを動かせるようにプログラムを作る
画像を置いただけではカーソルを操作できない。
コードでカーソルが動くようにしてやる必要がある。
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に乗っけてアタッチ。
③カーソルの位置から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 RayCastでキャラクターを検出する
■Topic
対象を検出したい
■方法
一般的に広く伝わるRayCastを使わせていただき、
「画像をクリックするとひとまずセリフがデバッグ表示される」
を目指す。
▼完成イメージ
①RayCastオブジェクトを作る
何はともあれRayCastオブジェクトがないといけないので、
Hierarchy上で
右クリック > Create Empty
でからのオブジェクトを作成。
名前をRayCastとする。
②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
にメインカメラを入れることができるので、
それを行ってゲームを実行すればセリフが再生されるはずです。
---
■参考にさせて頂いた記事
RayCastその4、Raycastを2Dで使う【Unity】 - (:3[kanのメモ帳]
Unity 2D画像を3D空間上に表示したい
■Topic
ダンガンロンパみたいに3D空間上に2Dキャラクターを表示したい。
が、意外と検索に苦労した。
■方法
▼目指す状況
①3D空間に板を置く
Unityの3D空間上に、まずはキャンバスとなる板を作ります。
Hierarchy > 3DObject > Quad で立ち絵っぽい感じになる板が作れます。
※Planeで作るとXZ方向(床)に板が作られるので床を作りたい場合はそちら。
②マテリアルを作る
3Dの板に画像を貼るためには、マテリアルを作る必要がある。
Projectタブ内に適当に
右クリック > create > Material
でマテリアルを作成する。
③マテリアルのShaderを設定する
そのまま貼っても透過が反映されなかったりして
思ったように表示されないので、
Shaderを設定する必要がある。
(この設定を調べるのにとても時間がとられた・・・)
Inspector > Shaderからプルダウンを見る > Unlit > Transparent
でShaderを設定する。
④画像を設定する
Selectから使いたい画像を設定する。
枠に画像を放り込んでもいいし、
Selectをクリックして適当に選んでもいい。
⑤マテリアルをオブジェクトに適用して画像を表示する
オブジェクトに作ったマテリアルを適用します。
オブジェクトにドラッグしてもいいし、
Inspector > Element01 から選択してもいい
表示自体はこれで完了ですが、矩形に沿った形になって不本意です。
⑥Scaleで形を調節する
悲しいことにデブっとした画像は
Scaleをいじって形を整えていくしかないっぽいです。
(対抗策あれば更新します…)
画像は事前に比率を決めておき、
スケールを一律で調整できるようにしておきましょう。
---
■参考にさせて頂いた記事