0から2Dアクションバトルゲームを作ろう!⑦ゲームに要素を追加していこう

0からアクションゲームを作ろう講座その7です。
ここまで開発してきたゲームに新たな仕様を追加実装し、ゲームの完成度を高めていきましょう!

この章でやること

現在開発を進めてきたゲームの状態は、「遊べない事もない」状態です。ゲームを起動するといきなり戦闘が始まり、そして短い時間で勝負がつきます。

またプレイヤーかボスのどちらかが消滅するとそこでゲームがストップします。
画面もまだ単純であり、プレイヤーが出来る事は少ないです。

ゲームの開発を始めて間もない時期や、いわゆるプロトタイプ品の作成時はだいたいこのようなものです。
既にゲームの全体像がイメージできるようにはなっているので、後はここに「ゲームを良くする」仕様を新たに実装するだけです。

この章では決まったテーマはありません。このゲームをもう少し楽しく遊べる作品に仕上げていきましょう。

実装する内容

この章では以下の開発作業を行っていきます。各項にて詳細を解説しています。

  1. 背景画像の実装
  2. プレイヤーキャラの新アクションの実装
  3. ここまでに発生したバグの修正
  4. タイトル画面の作成・制御

 

背景に画像を付ける

ここまで何度もテストプレイを行ってきて分かると思いますが、現在の真っ青なゲーム背景というのはとても地味です。
いわゆる「背景画像」の実装は、開発のモチベーションを維持する意味でも急務だといえます。

今回背景は1枚の画像を貼り付けるような形式にしますが、大きい画像をただ置くのでは簡単に終わりますので、「小さい画像をタイル状に敷き詰める」という新しい形をとってみます。

サンプル画像とインポート

上下左右に繰り返し貼り付けられるサンプル画像を以下にご用意しました。
勿論どんな画像でも良いのですが、1枚の画像をゲーム画面中に満遍なく敷き詰めるため、タイル間に不自然なつなぎ目が残るのはイマイチです。
画像の上下左右がこのようにシームレスに繋がっていると良いでしょう。

インポートした後のファイル名は「WallPaper」とします。

他に好きな一枚絵の画像を使いたいという場合には、大きめの画像ファイルを用意すればOKです。

背景画オブジェクトの作成

そして背景画像を表示させるスプライトオブジェクトを用意します。スクリプトは不要です。
いつものようにメニューから[GameObject]→[2D Object]→[Sprite]を選択します。
作成したオブジェクトの名前は「BackGround」辺りにしておきましょう。

オブジェクトのTransformコンポーネントに変な値が入っている場合は初期化をしましょう。

右上の歯車部分をクリックし、[Reset]を選択するとTransformの値がリセットされます。
ただし背景画像はゲーム画面を覆えていれば良いので多少ずれてても構いません。微調整は必要であれば後で行う事にします。

次にSprite RendererコンポーネントのSpriteパラメータに先ほど用意した背景画像をセットします。
そして背景画像は最背面に表示させたい為、Order in Layer(描画順)パラメータにマイナスの値を入力します。

今回のゲームではレイヤーをそれほど気にする必要はないのでとりあえず「-1」にしました。これで全てのスプライトより後ろに描画されるようになりました。

テクスチャをタイル貼り付けしない場合は、ここで背景画面の作成完了です。画像が小さくてゲーム画面を覆い切れていない場合、TransformコンポーネントのScale(拡大率)パラメータに大きい数値を入力してください。(倍率を同じにするため、X, Yには同じ数値を入れます。)

タイル貼り付けの設定

ここでスプライトをタイル貼り付けする場合はもう一手順必要です。

BackGroundのSpriteRendererコンポーネント中の「Draw Mode」パラメータを編集します。
ここではスプライトの描画方式を指定します。

  • Simple
    通常の描画方式です。スプライトの大きさはテクスチャの大きさとオブジェクトのScaleによってのみ決まります。
  • Sliced
    9スライスと呼ばれる設定を施したテクスチャで使用する描画方式です。テクスチャの特定の部分のみを引き延ばしながらサイズ変更をする事ができます。
  • Tiled
    スプライトの大きさを変更でき、その領域内にテクスチャをタイル貼り付けする描画方式です。

 

今回はTiledを選択しましょう。すると横のサイズ(Width)と縦のサイズ(Height)を指定する欄が現れます。
ここにゲーム画面を覆い切れるだけの大きな数字を入れましょう。サンプル画像の場合は20くらいでしょうか。

設定を終えたコンポーネントの状態はこのような感じです。

なお、シーンビューを見ると青の枠線から背景の画像がはみ出していますが、実際のプレイ画面では特に問題はありません。

これでゲーム画面に背景画像が表示されるようになりました。
色々な画像を用意して試すのも面白いかもしれません。

プレイヤーに出来る事を追加

今のゲームでプレイヤーに出来る事は弾と避けることとショット攻撃のみです。ゲームデザインによってはこれでも問題はありませんが、折角なのでもう1つプレイヤーにアクションを追加したいですね。

ボスとの一対一戦闘をメインにしたゲームなので、どのようなシステム・能力を実装するのかは制作者のセンスが問われる所です

例えば「威力は高いがリーチの短い近接攻撃」を実装したり、あるいは「条件付きで発動できる必殺技にしたり…」と色々考えてみるのも楽しいですが、この講座では、プレイヤーに追加する機能は敵弾を防ぐ「バリア」にします。

バリア機能の実装

講座のサンプルゲームを遊んでいただいた方なら、ゲーム中右クリックを押した時にバリアが展開されたのを確認できたと思います。
バリアの展開中は無敵となり、触れた敵弾は全て消滅させてしまいます。
右クリックを離すかエネルギー切れでバリアが解除されていました。

今回はこれと同じものを実装しますが、エネルギーの概念まではここでは実装せず、単に右クリックを離すまで無敵になる機能とします。

バリアそのものは1つのゲームオブジェクトになりますので、まずは画像をインポートしておきましょう。以下にサンプル画像を用意しています。
この画像はプレイヤーキャラの画像とサイズを合わせて作成したものなので、プレイヤーに別のテクスチャをあてている場合は別途サイズ調整等を行ってください。

インポートしたテクスチャの名前は(今までもそうでしたが)自由です。今回は「BarrierTexture」にしました。

バリアプレハブの作成

先ほど、バリアは1つのゲームオブジェクトとして実装するとしました。
この場合バリアは生成と消滅を繰り返すオブジェクトという事になります。そこで、今回はプレハブ化の機能を活用します。

まずはプレハブ化する元となるバリアオブジェクトを作成します。スプライトを持ちますのでメニューから[GameObject]→[2D Object]→[Sprite]の手順で作成しましょう。
オブジェクト名は「BarrierPrefab」とします。そしてSpriteに先ほどインポートしたバリアテクスチャをセットします。

また当たり判定の設定も必要です。敵弾との判定を取るので、「Rigidbody 2D」と「Circle Collider 2D」2つのコンポーネントを取り付けします。
Rigidbody2Dには[BodyType]にKInematicの指定をする事を忘れないでください。

CircleCollider2Dの設定もプレイヤーやボスとほぼ同じで、大きさだけ異なります。
[Is Trigger]にチェックを付けてトリガー設定にし、半径(Radius)を指定しましょう。
サンプル画像の場合はRadius「0.7」くらいが適切でしょうか。

ここまでのコンポーネントの設定は以下のようになります。最後にここにスクリプトの追加が必要になります。

 

バリアスクリプトの作成

バリアオブジェクトに取り付けるスクリプトの作成です。
といってもバリア側で処理すべき事は「触れた敵弾の消滅」だけなので非常にシンプルです。バリア自体の生成・消去処理についてはプレイヤースクリプトで行うからですね。
新たに「Barrier」スクリプトを作成し、以下のようにコーディングしましょう。

Barrier.cs

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

public class Barrier : MonoBehaviour
{
	// 当たり判定内に他オブジェクトが侵入した際呼び出されるメソッド
	void OnTriggerEnter2D (Collider2D collider)
	{
		// ボスが発射した弾でなければ処理を終了
		if (collider.gameObject.name != "EnemyBullet")
		{ // 接触オブジェクト名がEnemyBulletで無ければ
			return; // メソッド終了
		}

		// 弾オブジェクトを消滅させる
		Destroy (collider.gameObject);
	}
}

プレイヤー側で実装したの接触時判定メソッドを流用すれば簡単です。

スクリプトが出来上がったら、これを先ほどのBarrierPrefabにアタッチします。

バリアのプレハブ化

スクリプトのアタッチまで終えたら、あとはプレハブ化だけですので復習しましょう。
プレハブにしたいゲームオブジェクトをヒエラルキーウィンドウからプロジェクトウィンドウにドラッグアンドドロップします。

そして元のオブジェクトをヒエラルキーウィンドウ上から削除すれば完了です。

バリアの生成・消去

バリア本体が完成したので、最後にこれをプレイヤー側のスクリプトで生成・消去をさせるだけです。
「バリア展開中はショットを撃てない」仕様の実装もここで行いましょう。

PlayerController.cs

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

public class PlayerController : MonoBehaviour
{
	// メンバ変数宣言
	public GameManager gameManager;		// ゲームマネージャー
	public GameObject bulletPrefab;		// 弾のプレハブ
	public GameObject barrierPrefab;    // バリアのプレハブ
	private GameObject barrierInstance;	// バリアのインスタンス(実体)
	private int health; // 体力

	// 起動時に1回だけ呼び出されるメソッド
	void Start ()
	{
		(省略)
	}

	// 毎フレーム呼び出されるメソッド
	void Update ()
	{
		// -----移動処理-----
		// マウスカーソルの座標をVector2型変数cursorPosに取得
		Vector2 cursorPos = Input.mousePosition;
		// cursorPos内の座標データをスクリーン座標からワールド座標に変換する
		cursorPos = Camera.main.ScreenToWorldPoint (cursorPos);
		// Transformコンポーネントのpositionに計算したcursorPosを代入
		transform.position = cursorPos;

		// -----弾発射処理-----
		if (Input.GetMouseButtonDown (0) && barrierInstance == null)
		{ // 左クリックを押された瞬間かつ、バリアの実体が存在しない時
			// GameObject型ローカル変数を宣言 (生成したインスタンスを格納する)
			GameObject obj;
			// 弾プレハブのインスタンスを生成し、変数objに格納
			obj = Instantiate (bulletPrefab);
			// 弾インスタンスの座標にプレイヤーの座標をセット
			obj.transform.position = transform.position;
			// インスタンスのオブジェクト名を変更(敵弾と区別するため)
			obj.name = "PlayerBullet";
			// 弾のパラメータをセット
			obj.GetComponent<Bullet> ().speed = 6.0f;       // 速度
			obj.GetComponent<Bullet> ().angle = 0.0f;		// 角度
			obj.GetComponent<Bullet> ().limitTime = 5.0f;   // 生存時間
			// 弾の色を変更
			obj.GetComponent<SpriteRenderer> ().color = Color.cyan; // シアン
		}

		// -----バリア処理-----
		// バリア展開
		if (Input.GetMouseButtonDown (1) && barrierInstance == null)
		{ // 右クリックを押された瞬間かつ、バリアの実体が存在しない時
			// バリアの実体を生成し、親オブジェクトを自身のオブジェクトに指定する
			// 変数barrierInstanceに実体の参照をセット
			barrierInstance = Instantiate (barrierPrefab, transform);
			// バリア実体のローカル座標(親との相対距離)を0で初期化
			barrierInstance.transform.localPosition = new Vector3 (0.0f, 0.0f, 0.0f);
		}
		// バリア消去
		if (Input.GetMouseButtonUp (1) && barrierInstance != null)
		{ // 右クリックが離された瞬間かつ、バリアの実体が存在する時
			// バリアの実体を消去
			Destroy (barrierInstance);
			// 変数barrierInstanceを初期化
			barrierInstance = null;
		}
	}

	// 当たり判定内に他オブジェクトが侵入した際呼び出されるメソッド
	void OnTriggerEnter2D (Collider2D collider)
	{
		(省略)
	}
}

スクリプトの記述が完了したら、「BarrierPrefab」を忘れずにセットしましょう。

バリアのプレハブは今まで通りpublicメンバ変数の機能でセットします。
それをInstantiate()メソッドでインスタンスを生成するのも今までと同じです。

ただし今回はInstantiate()の第2引数に自身のTransformをセットする事で、実体の親オブジェクトに自身のオブジェクトを指定します。(親子関係を管理しているのはTransformコンポーネントだと覚えておいてください。)
これによって、特にバリア側に移動処理が無くてもプレイヤーにくっついて移動してくれるようになります。
ただし、もしローカル座標(親との相対座標)に変な値が入っているとその分位置がずれる為、念のため0のVector3型を代入して初期化しています。

またスクリプト中でたびたび出てくる「null」は、「何もない」事を示す単語です。
例えば今回出てきた変数barrierInstanceはGameObject型であり、何らかの実体の参照を格納するのですが、この場合nullを指定する事が可能です。(変数の宣言時は既にnullになっています。)
普通の数値情報などとは勝手が変わり、覚えにくいですがとても大事なのでぜひ覚えておきたいです。

 

nullについては勘違いをしやすいので補足しますが、null(無)と数値の0(数値情報)は別物です。また、intやfloatなどの「値型」と呼ばれる変数型はnullを指定できません。原理を理解するのは大変なので、最初は感覚で慣れていくと良いです。

また、GameObject型などは「参照型」と呼ばれておりnullを指定可能ですが、nullのままその変数で参照を行うと(例えばメンバ変数への書き込みなどをすると)エラーが発生します。

 

バグや不自然な動作の修正

ここでテストプレイを行っていると気が付くかもしれませんが、、実は度々エラーが発生しています。
プロジェクトウィンドウと同じ場所にあるコンソールウィンドウをタブ切り替えで表示させて確認しましょう。

ここで赤色のマークと共に表示されているのは全てエラー文です。

エラーが出ても、一見ゲームが正常に動いているように見える場合もあります。
ただしエラーは本来発生してはいけない存在なので、例え無害でもすべてを修正してから次に進みましょう。

問題点を見つけよう

現在「プレイヤーが消えている」状態と「ボスが生きている」状態が重なるとエラーが発生します。
この原因はボスオブジェクトにあります。エラー文をダブルクリックするとスクリプトの該当行を確認できるので見ていきましょう。

このエラーは弾発射時に、「プレイヤーオブジェクトが無いのにプレイヤーの座標を取得しようとした」為に発生しています。
エラー文に、
「The object of type ‘GameObject’ has been destroyed but you are still trying to access it.」
と書かれている事に注意してください。

またもう一つ不具合として、「バリアを展開しているのにダメージを受けてしまう」という現象があります。
これは修正は簡単ですが、1回のテストプレイでは気づきにくい事もあります。

テストプレイ時は広い視点を持ち、色々な可能性を予測しながら行えるように意識できると良いでしょう。

null参照にまつわる不具合

まずは「プレイヤーが居ないのにプレイヤーを参照してしまう」問題に対処します。
弾発射前にプレイヤーが生きているかどうかを確認し、消えていたら発射処理そのものを中断するようにしてみましょう。

BossController.cs内Update()メソッド

	// 毎フレーム呼び出されるメソッド
	void Update ()
	{
		// 経過時間をカウント
		time += Time.deltaTime;

		// -----弾発射処理-----
		if (playerObj != null)
		{ // プレイヤーオブジェクトが存在する時
		  // 0.4秒ごとに弾を発射
			if (time > 0.4f)
			{ // 経過時間が0.4秒より大きければ
			  // 経過時間をリセット
				time -= 0.4f;

				// 高速弾を発射
				Shot (8.0f, GetAngleToPlayer (), 5.0f);
				// 3way弾を発射
				Shot (5.0f, GetAngleToPlayer () - 20.0f, 5.0f);
				Shot (5.0f, GetAngleToPlayer (), 5.0f);
				Shot (5.0f, GetAngleToPlayer () + 20.0f, 5.0f);
			}
		}
	}

このような条件式でオブジェクトがnullでない事を確認する処理は一般的に「nullチェック」などと呼ばれます。
使用頻度が高いので覚えておきましょう。

バリアにまつわる不具合

次にバリアに関する不具合の修正です。
「バリア展開中はプレイヤーが無敵」になるようにすれば終わりです。今までは無敵ではなかった為、弾とプレイヤーが重なるとダメージを受けてしまっていました。

PlayerController.cs内OnTriggerEnter2D()メソッド

	// 当たり判定内に他オブジェクトが侵入した際呼び出されるメソッド
	void OnTriggerEnter2D (Collider2D collider)
	{
		// ボスが発射した弾でなければ処理を終了
		if (collider.gameObject.name != "EnemyBullet")
		{ // 接触オブジェクト名がEnemyBulletで無ければ
			return; // メソッド終了
		}
		// バリア展開中なら処理を終了
		if (barrierInstance != null)
			return;

		// 弾オブジェクトを消滅させる
		Destroy (collider.gameObject);

		// 自身の体力を1減らす
		health--;
		// 現在体力をUIに表示
		gameManager.SetPlayerHealthUI (health);
		// プレイヤー消滅処理
		if (health <= 0)
		{// プレイヤーの体力が0以下
			Destroy (gameObject); // 自オブジェクト消去
		}
	}

if文において、条件分岐後の処理が1つだけであれば波かっこ{}の記述を省略できます。

これで不具合らしき動作は無くなったはずです。もう一度テストプレイで確認してみましょう。

このようにマウスで「右クリック」するとバリアが発生し、ボスの弾を受けないようになっていれば成功です!

タイトル画面の開発

今まではずっとバトル画面の開発を行ってきました。少しずつキリがついてきたこのタイミングで、そろそろタイトル画面の開発をしてみましょう。

Unityでは各画面の管理においてシーン(Scene)というシステムが使われています。
シーンごとに画面が分けられ、シーンには「どのゲームオブジェクトが配置され、パラメータが何であるか」の情報が記録されています。

今までの開発で沢山のオブジェクトを作成し、コンポーネントの設定をしてきましたが、それらは全て1つのシーンに保存されていました。

プロジェクトウィンドウを確認すると[Scenes]フォルダ内に「SampleScene」というファイルがありますが、これにバトル画面のデータが入っています。

タイトル画面にはもちろんバトル画面に配置してきたオブジェクトは必要ありません。ですので新しいシーンを作成し、1からオブジェクトの作成・配置を行っていく事になります。

シーンの作成と保存

シーンの新規作成はメニュー又はプロジェクトウィンドウから行います。
メニュー操作の場合は[File]→[New Scene]を選択すれば完了です。

ヒエラルキーウィンドウやシーンビューを確認すると、ゲームオブジェクトの情報が初期化されているのが分かります。
先ほどのSampleSceneシーンを開けばまたバトル画面の開発に戻れますので心配は不要です。

まだ未編集の今のシーンですが、まずは名前を付けて保存をしておきます。
同じくメニューバーの[File]から[Save Scene As…]を選択するとファイル保存ダイアログが開きます。


ここではAssetsフォルダ内に元から入っていた「Scenes」フォルダに「TitleScene」というシーン名で保存をします。

後は編集を加えた場合に、適宜上書き保存をしていくだけでOKです。

*Macの場合は

タイトル画面で使う素材

タイトル画面にはやはりタイトルロゴを表示させたいですね。
Textコンポーネントを使用するのでも問題はありませんが、画像を使った方が綺麗に作りやすいです。

以下にサンプルのタイトルロゴを用意しました。タイトルはとりあえず「Action Battle Game」としています。

また背景画像もバトルとは違う物を使用します。
再びタイル形式で貼り付けるので、上下左右をシームレスに接続できる画像を用意すると良いでしょう。以下がサンプルです。

インポートしたテクスチャ名は自分が分かりやすい名前を付ければ良いでしょう。例としてはタイトルロゴを「TitleLogo」、背景画像を「TitleWallPaper」にしました。

Imageオブジェクトの作成・配置

タイトル画面のデザインは背景画像以外すべてUIで作成する事にします。
まずはタイトルロゴを配置するので、先ほど追加したシーンを選択していることを確認し、メニューから[GameObject]→[UI]→[Image]を選択しましょう。
Canvasオブジェクトと共にImageオブジェクトが作成されます。Canvasをダブルクリックし、シーンビューの中心に表示させておきましょう。

後はImageオブジェクトの名前を「Logo」などにしておき、テクスチャのセット・位置や大きさの調整をするだけです。
大きさの調整はScaleパラメータのxとyそれぞれに「1.4」辺りを入力すれば良いでしょう。
ただし、テクスチャをセットした直後はテクスチャ自体の大きさがRect Transformコンポーネントに反映されていません。
そんな時はImageコンポーネント中の「Set Native Size」ボタンを押すと解決されます。

Buttonオブジェクトの作成・配置

タイトル画面に必要な要素として、「ゲーム(バトル)を開始させる為の操作」があります。
それを今回はUIを介して実装してみましょう。

前章で作成したUIはデータの表示のみを行っていましたが、ここではユーザーからの操作を受けとる「Button」のUIを作成していきます。

まずはButtonオブジェクトを配置してみましょう。(メニューもしくは右クリックどちらでも大丈夫です)

作成されたButtonはひとまず画面下部に大きくして置いておきます。

そしてButtonオブジェクトを確認すると、子オブジェクトとして「Text」を持っている事が分かると思います。

これはボタン中央部にある「Button」という文字列を表示させています。
ゲーム開始用の押しボタンである事を分かりやすくする為、コンポーネントの設定を変更しましょう。

さて、ボタン入力を受け取りゲーム画面へと移る処理を作成…と行きたい所ですが、シーンの間をまたぐ処理は事前に「Build Setting」によるシーン登録設定が必要になります。

ビルドに関する説明は次章で行いますので、画面遷移処理も次章での実装とします。

タイトル画面のデザインを改良

画面遷移を後回しにする代わりに、タイトル画面のデザインにもう少し手を加えていきます。

背景画像の表示

先ほどインポートした背景画像を、章の冒頭で行ったような「タイル貼り付け」で表示させていきます。
スプライトオブジェクトを作成して、先ほど追加した背景用のテクスチャをセットしましょう。

そして[Draw Mode]パラメータにTiledを選択し、出てきた[Size]パラメータに大きい数値を入力するだけです。それぞれ「20」くらいずつ入力すれば大丈夫です。(必要であれば[Order in Layer]も設定します。)

ピクチャーを配置

タイトル画面の上半分が寂しい為、何かモノを配置してみましょう。
とりあえずプレイヤーとボスのテクスチャを表示させる事で埋めておこうかと思います。

Imageオブジェクトを2つ作成し、それぞれテクスチャをセットして好きなように配置をします。

ピクチャーに動きを追加

ゲーム画面というのはユーザーが操作をしていない間でも何らかの動きがあった方が良いと言われています。
このタイトル画面にも何か動くモノを追加したいです。ここでは先ほどのプレイヤー・ボス画像を揺らしてみます。

バトル画面で作成した時と同じように、「TitleManager」オブジェクト及びコンポーネントを用意します。
このスクリプトはこの先バトル画面への画面遷移にも使用します。

オブジェクトはメニューから[GameObject]→[Create Empty]で作成でしたね。
そしてTitleManagerスクリプトも作成してアタッチしておきます。

指定したオブジェクトを上下に揺らす動きはこのようなスクリプトで実現できます。
TitleManager.cs

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

// タイトル管理スクリプト
public class TitleManager : MonoBehaviour {

	// メンバ変数宣言
	public GameObject playerPicture;	// プレイヤー画像UI
	public GameObject bossPicture;      // ボス画像UI
	private Vector2 playerPicDefaultPos;    // プレイヤー画像UIの初期座標
	private Vector2 bossPicDefaultPos;      // ボス画像UIの初期座標
	private float time;	// 経過時間

	// 起動時に1回だけ呼び出されるメソッド
	void Start ()
	{
		// 変数初期化処理
		playerPicDefaultPos = playerPicture.transform.position; // プレイヤー画像UIの初期座標取得
		bossPicDefaultPos = bossPicture.transform.position;     // ボス画像UIの初期座標取得
		time = 0.0f;
	}

	// 毎フレーム呼び出されるメソッド
	void Update ()
	{
		// 経過時間をカウント
		time += Time.deltaTime;

		// プレイヤー画像UIを時間経過で上下に揺らす
		Vector2 playerPicFixPos = new Vector2 (0.0f, Mathf.Sin (time * 1.5f) * 50.0f);	// 移動量計算
		playerPicture.transform.position = playerPicDefaultPos + playerPicFixPos;		// 初期座標に移動量を足した値を座標にセット

		// ボス画像UIを時間経過で上下に揺らす
		Vector2 bossPicFixPos = new Vector2 (0.0f, Mathf.Sin (time) * 30.0f);   // 移動量計算
		bossPicture.transform.position = bossPicDefaultPos + bossPicFixPos;     // 初期座標に移動量を足した値を座標にセット
	}
}

スクリプトの入力が完了したら、上の画像のように「PlayerPicture」と「BossPicture」をセットするのを忘れないようにしましょう。

ちなみに、移動量計算の部分はややこしい計算式になっていますが現段階では覚える必要はありません。
テストプレイをすると分かりますが、このような動きはMathf.Sin()メソッド等を使えば良い、という事だけ記憶しておきましょう。

ボタンのテクスチャを変更

先ほど配置したButtonに使われている画像はUnity標準のものです。
画像は自分で用意したものに変更する事が可能です。

とりあえず変えてみたい方向けにサンプル画像を提供します。


この画像をインポートし、ButtonオブジェクトのImageコンポーネント内[Source Image]にセットをすると変更が完了します。
アスペクト比が違うため画像が歪んでいますが、ボタンの大きさが変わるためSetNativeSizeボタンは押すべきではありません。

このサンプル画像では9スライスに対応しているので、テクスチャに分割の設定を施し、Imageコンポーネント内[Image Type]パラメータにSlicedを選択すると綺麗に表示をさせる事が出来ます。
手順が複雑で必須の仕様でもないため説明は割愛しますが、途中経過の画像を用意していますのでチャレンジされる方はあくまで参考にしてください。

*なお上記の手順を行わないと下のようになりますが、特に問題はないので今後はこのまま進めます。

ここまでのおさらい

ゲームにいくつかの要素を実装し、少しは遊びやすくかつ楽しみやすくなっていきました。
タイトル画面とバトル画面の繋がりだけは未実装ですが、これは次章で作業をします。

この章で学んだ知識は使える場面の限定されるものも多いですが、ゲーム開発は汎用的な知識だけでは行えません。
何かの仕様を実装したい時、知っている事のみで出来ない時はネットや書籍等で調べたり自分で研究をする事も大事になります。

次章で学ぶこと

「ゲームをビルドする」という事を学び、テストプレイではなく実際にこのゲームを遊べる形に仕上げていきます。
未完成だったタイトル画面の処理も完成させる事ができます。これでやっと一区切りがつくので頑張りましょう!

 

<前回>  <=  「⑥UIを表示してみよう

<次回>  =>  「⑧ビルドをしてゲームを遊んでみよう