14日目 Unity 全体のシーンを管理する(ボタンによるシーンの行き来、クエストクリア時のシーン移動)
<全体のシーンを管理する>
1.まずは新しいSceneを作成し、Buttonを追加する(Townの画面)
このButtonのサイズを他のButtonと一致させたいときは、Button内のRect Transformをコピーして貼り付ける(これを応用すれば、Textなどのサイズも合わせられる)
2.スクリプトを作成する
A
public void LoadTo(string sceneName) //()のシーンに飛ぶ
{
SceneManager.LoadScene(sceneName);
}
これをEmptyに追加し、StageUIのボタンに追加(詳細は6日目を参照)、その中から今回新しく作った関数を選択。(OnClickで)
Aの関数を設定すると、その下に入力する部分がある。そこに飛ぶ先のシーン名を入力しておく。
この状態でボタンを押してもエラーが出る。
3.Build Settingで作成したシーンを追加する
4.クエストクリア時にシーンの移動をするスクリプトを作成する
B
public SceneTransition sceneTransition; //Aのスクリプトを変数で取得する
if (encountTable.Length <= currentStage) //クエストクリア時の処理
{
Debug.Log("クエストクリア");
//クリアの処理
QuestClear();
}
void QuestClear()
{
sceneTransition.LoadTo("Town"); //AのLoadTo関数を使用する
}
<クエストクリアの演出>
1.さらに新しいSceneを作成(タイトル画面)
2.ボタンを配置し(今まで学んだことを応用し、Town画面へ飛ぶように)、ステージクリアのTextを追加する
3.StageUIのスクリプトの編集
C(StageUIを管理するスクリプト)
public GameObject stageClearText; //非表示にしたいときはGameObjectで取得する
private void Start()
{
stageClearText.SetActive(false);
}
public void ShowClearText()
{
//ここで進むボタンを非表示にし、ステージクリアのテキストと戻るボタンのみ表示する
stageClearText.SetActive(true);
nextButton.SetActive(false);
toTownButton.SetActive(true);
}
D(クエスト全体を管理するスクリプト)
void QuestClear() { // クエストクリアと表示する // 街に戻るボタンのみ表示する stageUI.ShowClearText();
}
感想
今回の学習でゲームの進行に関する部分の設定はほぼ終わりました!88888888
ただ、このままだととてもではないですがゲームの画面には見えないため、次回からは画面の演出や背景といった魅せる部分の設定方法を学んでいきます!
ですが、ここまで学習しておいてなんですが、やはり今までの復習を兼ねて1から復習するべきなのかなと思います。。。というのも、わかっているつもりでも自分の力になっていない部分も多く残っており、今後ゲーム開発をする際にもっと学んでおけばよかったと後悔しないよう、基礎をしっかりと身につけておきたいからです。悲観ではなく、将来の自分の力にしたいという希望からですね( ´∀` )
ここまででUnityでのゲーム開発第一期が終了ということになりそうです。
勉強時間合計:25.5h
Unity 13日 後半 バトル終了後にボタンの再表示、敵のステータスの表示方法
<バトル終了後にボタンの再表示>
A(バトルの管理)
public class BattleManager : MonoBehaviour
public QuestManager questManager; //Bを持つオブジェクトをインスペクターで貼り付け
void EndBattle()
{
questManager.EndBattle(); //BのEndBattleを行う
}
B(クエストの進行などの管理)
public class QuestManager : MonoBehaviour
public StageUIManager stageUI; //Cを持つオブジェクトをインスペクターで貼り付け
public void EndBattle()
{
stageUI.ShowButtons(); //CのShowButtonsを行う
}
C(ステージUIを管理)
public class StageUIManager : MonoBehaviour
{
public Text stageText;
public GameObject nextButton; //インスペクターでボタンの取得
public GameObject goBackButton;
public void ShowButtons()
{
nextButton.SetActive(true); //ボタンの再表示
goBackButton.SetActive(true);
}
<敵のステータスUIの表示>
クエスト開始時には表示せず、エンカウントしたときに表示するには
public class BattleManager : MonoBehaviour
public EnemyUIManager enemyUI;
①private void Start() //スタート時は非表示に
{
enemyUI.gameObject.SetActive(false); //enemyUIがついているゲームオブジェクトを非表示にするためgameObjectが必要
}
②public void Setup(EnemyManager enemyManager) //エンカウント時に表示
{
enemyUI.gameObject.SetActive(true);
}
③void PlayerAttack() //倒したときに非表示に
{
player.Attack(enemy);
enemyUI.UpdateUI(enemy);
if(enemy.hp == 0)
{
Destroy(enemy.gameObject);
enemyUI.gameObject.SetActive(false);
EndBattle();
}
else
{
EnemyTurn();
}
}
感想
ここまできてやっとゴールが見えてきました!ゲームのシステムでいえば、残りはクエストクリア時の切り替えだけですね。とはいえ、画面演出の部分やサウンドなど、ゲームをよりクオリティの高いものにするために必要なことはこれから学ぶので、キリの良いところで今までの復習をするか先に進むかを決めたいと思います。
このブログに書ききれていないところもあるので不安ではありますが、C#のスクリプトに関して言えば8割程度理解はできるようになりました。やっぱり書籍で読むよりも、手を実際に動かしながらまねして進めるほうが効率がいいですね( ´∀` )
勉強時間合計:24h
13日目 前半 外部の関数の取得、敵の撃破(Destroy)
<Aのとき(クリックした時)にB の関数が呼ばれるようにするには>
A
public class EnemyManager : MonoBehaviour
public void OnTap()
{
Debug.Log("クリックしました");
}
B
void PlayerAttack()
{
player.Attack(enemy);
enemyUI.UpdateUI(enemy);
}
Aに
using System;
Action tapAction; //クリックした時に実行したい関数(外部から設定したい)
public void AddEventListenerOnTap(Action action) //tapActionに関数を登録する
{
tapAction += action; //引数としてPlayerAttackを受け取っている
}
public void OnTap()
{
tapAction();
}
Bに
public void Setup(EnemyManager enemyManager)
{
enemy.AddEventListenerOnTap(PlayerAttack); //PlayerAttackを引数として関数を使う→上のtapActionに加える
}
<敵の撃破(Destroy)>
void PlayerAttack() //攻撃時の関数
{
player.Attack(enemy);
enemyUI.UpdateUI(enemy);
if(enemy.hp == 0) //簡単なif文で、撃破時と相手のターンに分岐させる
{
Destroy(enemy.gameObject); //hpが0の時、ゲームオブジェクトの消滅
EndBattle();
}
else
{
EnemyTurn();
}
}
void EnemyTurn()
{
enemy.Attack(player);
playerUI.UpdateUI(player);
}
void EndBattle()
{
Debug.Log("ゲーム終了");
}
12日目 Unity Prefabの情報(ステータス)をそのまま使う方法、引数について
引数の使い方であいまいな部分があったため、ここに記しておきます。
<A>(関数を使う側)
void EncountEnemy()
{
GameObject enemyObj = Instantiate(enemyPrefab); //読み込んだ画像の表示
EnemyManager enemy = enemyObj.GetComponent<EnemyManager>();
//enemyObjの中のEnemyManagerを取得する
battleManager.Setup(enemy); //EnemyManager型の変数
//()内にenemyを入れるために、上の文で取得しておく必要がある
}
<B>(関数を作っている側)
EnemyManager enemy; //publicはつけない(なぜならA で取得しているから)、これは、このスクリプト内で使う変数を作成しているだけ
public void Setup(EnemyManager enemyManager) //EnemyManager型の変数を受け取る関数
{
enemy = enemyManager; //作成した変数=引数にするという意味
enemyUI.SetupUI(enemy);
}
<GetComponentで直接Prefabの情報を取得したのはなぜか>
public void Setup(EnemyManager enemyManager)
このように、関数で扱う引数の型が決まっているときは、関数を作る側でも引数の型の指定をしなければなりません。
今まではヒエラルキー上でEnemyManager(敵のステータス等を設定するもの)を使っていました。しかし、AのスクリプトのようにGetComponentで直接Prefabの情報を取得すれば、EnemyManagerがなくとも元々Prefabに設定されているステータスがそのまま反映されます。
感想
本日は引数の宣言において型を設定するということを学びました。(今までも使っていたのにやっと解決しました・・・)
いままで敵のステータスを設定するためにEnemyManagerというオブジェクトを使っていました。そこで、Prefabの情報を引数としてそのまま使うことで、Prefabに設定されたステータスを用いることができると分かりました。(理解するまでに多大な時間が(´;ω;`))
引数の型の宣言と、GetComponentを同時に使うことでここまで分からなくなるのかと心配になりましたが、オブジェクトが1つ少なくなったため見やすいですね。
勉強時間合計:23h
11日目 Unity 関数の使用方法、クリック検出
関数についてもう一度おさらいします
Aのスクリプトにある関数をBで使いたいとき
<A>
public class PlayerUIManager : MonoBehaviour
{
public void UpdateUI(Player player) //使いたい関数
}
<B>
public PlayerUIManager playerUI; //これにより、使いたい関数のあるスクリプトを取得する
void EnemyAttack()
{
playerUI.UpdateUI(player); //関数の使用
}
少しはわかりやすくまとめられたかな。。。?
クリック検出
これはUIのボタンではなく、Imageで作ったPrefabなどに対してクリックするというときに使います。
①PrefabをOpenPrefab
②PrehabにColliderとEvent Triggerを追加する。Prefabに使う関数が入っているスクリプトを貼り付ける。
③Event Triggerでタイミングを設定(Pointer Click等)し、そこに②のPrefabを貼り付け、さらに使いたいスクリプト、その中の関数を設定する
④カメラにRaycaster(例えば2Dの場合はPhysics 2D Raycaster)を追加する
これで敵が出現した際に、敵のPrefabをクリックすると攻撃等できるようになります。
現時点での、スクリプトの全体像
①クエスト全体を管理するもの(ステージの進行と敵とのエンカウント)
②ステージのUIを管理するもの(ボタンやステージ進行度)
③バトルを管理するもの(④~⑦のタイミング等をまとめて管理する)
④プレイヤーのUI(攻撃時のHP反映)
⑤プレイヤーのステータス(HPやATの設定と攻撃、ダメージ)
⑥エネミーのUI(攻撃時のHP反映)
⑦エネミーのステータス(HPやATの設定と攻撃、ダメージ)
感想
本日はクリック検出、攻撃した際にプレイヤーとエネミーのUI(HPやAT、名前)に反映させるということを行いました。いきなりスクリプトとオブジェクトの数が多くなり、それぞれどこに結びついているのかが分かりづらくなりました。作成していく中では、関数の出発点(クリックした時)などを明確にしておくことで全体の順序を把握することが重要ですね( ´∀` )
あともう一つ、関数を設定するときは、初めにvoid Startでデバッグし、ミスがないかをその都度確認することが大切だと学びました!
勉強時間合計:21h
10日目 Unity 2Dゲームの作成開始!
こんにちは( ´∀` )
やっと本格的に製作が始まりますね。なんだかんだ毎日少しずつ触っているせいか、スクリプトの構造を1回の説明で理解できるようになってきました…!
本日学んだこと(復習もあるよ)
1.あるオブジェクトの中身を変更したいとき
Ex.Text public Text stagetext;
//これをオブジェクトに貼ると、インスペクター上にオブジェクトを貼り付けられるようになる。そこに貼ったオブジェクトの中のTextをstagetextという変数で扱うよという意味です。
2.textの中身を変更する方法
これは1の続きになりますが、今回は2つの方法を挙げます。
①int型のものをstring型に変換して代入したいとき
stageText.text = currentStage.ToString(); //currentStageはもともとint型
②int型のものとstring型のものを両方使いたい場合
stageText.text = string.Format("Stage:{0}", currentStage+1); //string.Formatを使えば、このようにもともとint型であっても組み合わせられる。
3.他のスクリプトの中身(関数)などを使うとき
public StageUIManager stageUI; ////これをオブジェクトに貼ると、インスペクター上にオブジェクトを貼り付けられるようになる。そこに貼ったオブジェクトの中のStageUIManagerというスクリプトをstageUIという変数で受け取るという意味です。
4.敵とのエンカウント設定
int encountTable = { -1, -1, 0, -1, 0, -1 }; //(-1なら遭遇しない、0なら遭遇)
//宣言と初期化を同時に行っているためnew intは不要です
public void OnNextButton()
{
if(encountTable[currentStage] == 0) //ステージ1の時、encountTable[1]となる
{
Debug.Log("敵に遭遇");
}
}
5.モンスターの表示
アセットストアからインポート→ヒエラルキーに入れて位置など調整→Prefabとして保存(Projectにドラッグ&ドロップ)
public GameObject enemyPrefab; //作ったPrefabをゲームオブジェクトとして、enemyprefabという関数で受け取る
else if(encountTable[currentStage] == 0) //4でエンカウントを設定したが、そのタイミングでEncountEnemyが行われるよという意味
{
EncountEnemy();
}
void EncountEnemy()
{
Instantiate(enemyPrefab); //読み込んだ画像の表示
}
6.モンスター遭遇時にボタンを消す方法
A(ボタンを管理するスクリプト)
public GameObject nextButton;
public GameObject goBackButton;
public void HideButtons() //ボタンを非表示にする関数
{
nextButton.SetActive(false);
goBackButton.SetActive(false);
}
public void ShowButtons() //ボタンを表示する関数
{
nextButton.SetActive(true);
goBackButton.SetActive(true);
}
public StageUIManager stageUI;(Aのスクリプト)
void EncountEnemy()
{
stageUI.HideButtons(); //Aの関数を使用する
Instantiate(enemyPrefab); //Prefabの表示
}
感想
本日学んだ範囲は今までの範囲を実際に使いこなすというもので、他のスクリプト等の取得や関数の結びつきなど分かりやすく感じました。(一から作るのとは全く違いますが)
少し成長を感じております!スクリプトをデバッグで学ぶだけでなく、実際にゲームの画面が出来上がっていくのをみると、作業もより集中して行うことができますね…!
勉強時間合計:19h