Unity(C#)初心者・入門者向けチュートリアル ひよこのたまご

AndroidやiOS向けアプリを簡単に作れるゲーム開発環境Unity(ユニティ)の使い方を、チュートリアル方式で一緒に学びましょう!

【Unity2】近況報告&ブロック崩しにアイテム生成機能を追加したよ!githubにもアップ!【ブロック崩し6】

Unity5.2.1f1 Personal(2016年3月)


皆様お久しぶりです!(・∀・)


ひよこのたまごをそろそろ更新しないとな〜と思いつつ、ずいぶんと更新できていませんでした〜
ちょっと忙しかったのです・・・しかし、その甲斐あって・・・


無事仕事が決まりましたー!


いきなりなんだ!?と思うかもしれませんが、このブログをはじめるくらいのタイミングで前職を退職しまして、
Unityの勉強のために時間をとっていたのです〜
今はスマホゲームを作る会社で、無事Unityを使ってゲームの開発をしております〜


アウトプットすることでよりUnityの理解が進むし、面接で自分のレベルを伝える時の参考になるだろうと思い始めたのですが、
無事仕事が決まったということで、ブログを続けていて本当によかったです!


前ほどの頻度では更新できないかと思いますが、これからもなるべく皆様に分かりやすいように
Unityの知識を書いていきたいと思いますので、今後ともどうぞよろしくお願い致します〜


ブロック崩しにアイテム生成機能を追加!

Facebookへお問い合わせを頂きました!
以前作成したブロック崩しにアイテム生成機能を追加する方法を知りたいとのことで、
ブロック崩しを更新致しました〜


以下githubのrepositoryにアップしましたので、気になる方はダウンロードしてみて下さい〜


github.com


それでは解説です〜


①ResourcesフォルダにItemプレファブを作成
まずは問題のItemプレファブを作成します〜
プレファブがよく分からないという方は以下ページを参考に作成して下さい〜


【Unity開発】Prefabまとめ【ひよこエッセンス】 - Unity5(C#)初心者・入門者向けチュートリアル ひよこのたまご


ItemプレファブのInspectorビューはこのようになっております〜
tagがItemになっている点に、ご注意ください〜!


f:id:hiyotama:20160312183346j:plain
Itemプレファブ


作成したら、ProjectビューにResourcesフォルダを作成し、その中にPrefabsフォルダを作成し、Itemプレファブを配置します〜


f:id:hiyotama:20160312183653j:plain
こんな感じ


続いてItemScriptというスクリプトを新規作成し、ItemプレファブにAddComponentします〜

using UnityEngine;
using System.Collections;

public class ItemScript : MonoBehaviour {

	//アイテムタイプのenum
	//PlayerScriptのOnTriggerEnterでアイテムの種類を判別するために利用
	public enum ItemType{
		ExtendPlayerLength,
		ShrinkPlayerLength,
	}
	public ItemType itemType;
	
	Rigidbody rb;
	Vector3 vec;
	float itemSpeed = -3.0f;
	
	// Use this for initialization
	void Start () {
		rb = GetComponent<Rigidbody>();
		vec = new Vector3(0, itemSpeed, 0);
	}
	
	// Update is called once per frame
	void Update () {
		rb.velocity = vec;
	}
}

ItemScript.cs


ゲーム画面に登場したら、一定の速度で下に落下しているという、ただそれだけのスクリプトでございます〜


enumは列挙型といって、アイテムの種類を指定しているだけなので、そんなに深く考えなくて大丈夫です〜
詳しくは以下ページを参考にして下さい〜


【Unity開発】enum(列挙型)まとめ【ひよこエッセンス】 - Unity5(C#)初心者・入門者向けチュートリアル ひよこのたまご


②ブロックを壊した時にアイテムを発生させる!
続いてブロックを壊した時に、ランダムでアイテムが発生するシステムを作っていきます〜


もともとあったBlockControllerというスクリプトに加筆していきます〜以下ソースです〜

using UnityEngine;
using System.Collections;

public class BlockController : MonoBehaviour {

	void OnCollisionEnter (Collision col)
	{
		Destroy (gameObject);

//********** 開始 **********//
		//アイテムを1/5の確立で生成
		if (Random.Range (0, 5) == 0) {
			CreateItem();
		}
//********** 終了 **********//
	}
	
//********** 開始 **********//
	void CreateItem(){
		//ResourcesフォルダからItemPrefab取得
		var item = Resources.Load<GameObject>("Prefabs/Item");
		//アイテムをHierarchy上に生成 positionはBlock, rotationはItemPrefab
		GameObject obj = Instantiate(item, gameObject.transform.position,item.transform.rotation) as GameObject;
		// 1/2の確立でアイテムの種類を決定
		switch(Random.Range(0, 2)){
		case 0:
			// 赤色にする
			obj.GetComponent<Renderer>().material.color = Color.red;
			// ItemTypeをExtendPlayerLengthにする
			obj.GetComponent<ItemScript>().itemType = ItemScript.ItemType.ExtendPlayerLength;
			break;
			
		case 1:
			// 黒色にする
			obj.GetComponent<Renderer>().material.color = Color.black;
			// ItemTypeをShrinkPlayerLengthにする
			obj.GetComponent<ItemScript>().itemType = ItemScript.ItemType.ShrinkPlayerLength;
			break;
			
		default:
			break;
		}
	}
//********** 終了 **********//
}

BlockController.cs


ボールが当たった時に1/5の確立でCreateItemメソッドを呼ぶようにしました〜
CreateItemメソッド1行目でやっているResources.Loadを使うことで、先程作成したResourcesフォルダからオブジェクトをロードすることができます〜

引数はResourcesフォルダ以下のパスです!


ロードするだけではゲーム画面に出現していないので、Instantiateメソッドを使いHierarchyビューに生成します〜
第2引数にはこのスクリプトのついているGameObject(つまりBlock)のPositionを、第3引数には実際にInstantiateするGameObject(つまりItem)のRotationを指定します〜


ここまできたらあとは簡単です!ランダムで2通りのアイテムを作成します〜

ひとつは赤色でItemTypeをExtendPlayerLengthに、もうひとつは黒色でItemTypeをShrinkPlayerLengthに指定します〜


③PlayerがItemに触れた時の挙動を追加
続いてPlayerであるバーがアイテムに触れた時に、アイテムの効果が発生するようにしていきます〜
具体的には赤いアイテムの時はバーが伸び、黒いアイテムの時はバーが縮みます〜


もともとあったPlayerScriptというスクリプトに加筆していきます〜以下ソースです〜

using UnityEngine;
using System.Collections;

public class PlayerScript : MonoBehaviour {
	private Vector3 pos;
	private Vector3 WorldPointPos;

//********** 開始 **********//
	private float playerLength; // バーの長さ
	// マウスが移動できる限界地点
	private float maxLeftPos = -1.9f;
	private float maxRightPos = 1.9f;
//********** 終了 **********//

	void Start(){
//********** 開始 **********//
		playerLength = transform.localScale.x;
//********** 終了 **********//
	}

	void Update (){
		// マウス位置座標をスクリーン座標からワールド座標に変換する
		WorldPointPos = Camera.main.ScreenToWorldPoint(Input.mousePosition);
		
//********** 開始 **********//
		// 壁を突き抜けないようにx軸の移動範囲を限定
		if (WorldPointPos.x <= maxLeftPos) {
			WorldPointPos.x = maxLeftPos;
		} else if (WorldPointPos.x >= maxRightPos) {
			WorldPointPos.x = maxRightPos;
		}
//********** 終了 **********//
		
		//y軸とz軸は固定
		WorldPointPos.y = -3.0f;
		WorldPointPos.z = 0.0f;
		
		// ワールド座標をPlayer位置へ変換
		gameObject.transform.position = WorldPointPos;
	}
	
//********** 開始 **********//
	void OnTriggerEnter (Collider col)
	{
		// アイテムにぶつかった時
		if (col.tag == "Item") {
			// アイテムを消す
			Destroy (col.gameObject);
			// ItemTypeによって、ExtendPlayerLengthかShrinkPlayerLengthどちらかを呼ぶ
			if (col.GetComponent<ItemScript> ().itemType == ItemScript.ItemType.ExtendPlayerLength) {
				ExtendPlayerLength();
			} else if(col.GetComponent<ItemScript>().itemType == ItemScript.ItemType.ShrinkPlayerLength){
				ShrinkPlayerLength();
			}
		}
	}
	
	void ExtendPlayerLength ()
	{
		// playerLengthを0.5長くする(2.5以上なら変更させない)
		playerLength += 0.5f;
		if (playerLength > 2.5f) {
			playerLength = 2.5f;
		}
		
		// 変更したplayerLengthをオブジェクトに反映する
		var temp = transform.localScale;
		temp.x = playerLength;
		gameObject.transform.localScale = temp; 
		
		// バーが長くなったので、マウスが移動できる限界地点を調整する
		maxLeftPos += 0.25f;
		maxRightPos -= 0.25f;
	}
	
	void ShrinkPlayerLength ()
	{
		// playerLengthを0.5短くする(1.0以下なら変更させない)
		playerLength -= 0.5f;
		if (playerLength < 1.0f) {
			playerLength = 1.0f;
		}
		
		// 変更したplayerLengthをオブジェクトに反映する
		var temp = transform.localScale;
		temp.x = playerLength;
		gameObject.transform.localScale = temp;
		
		// バーが短くなったので、マウスが移動できる限界地点を調整する
		maxLeftPos -= 0.25f;
		maxRightPos += 0.25f;
	}
//********** 終了 **********//
}

PlayerScript.cs


メンバ変数にplayerLength、maxLeftPos、maxRightPosを作り、StartメソッドでplayerLengthにバーの横幅を指定します〜
またアイテムを取りバーのサイズが変わるとバーが移動できる限界距離も変わってくるので、UpdateメソッドでmaxLeftPos、maxRightPosを使い、対処しています〜


そして新しく追加したOnTriggerEnterメソッドで、Itemタグの付いたオブジェクトがぶつかった時にItemTypeを判定し、それぞれメソッドを呼び出しています〜


赤いアイテムをとった時はExtendPlayerLengthメソッドが呼び出され、0.5伸ばし、同時にmaxLeftPos, maxRightPosも調整しています〜
黒いアイテムをとったらShrinkPlayerLengthを呼び0.5縮め、maxLeftPos, maxRightPosを調整しています〜


④取り損なったアイテムを消す

取り損なったアイテムをちゃんと消さないと、延々と落ち続けてしまいメモリの無駄遣いです〜


もともと作っていたBottomScriptに加筆します〜以下ソースです〜

using UnityEngine;
using System.Collections;

public class BottomScript : MonoBehaviour {
	public GameOverScript gameOver;
	bool goTitle = false;
	
	void Update (){
		if (goTitle) {
			//GameOverの文字が表示された状態で画面をクリック
			if(Input.GetMouseButtonDown (0)){
				Application.LoadLevel ("title");//タイトル画面へ遷移
			}
		}
	}
	
	void OnCollisionEnter(Collision col) {
		Destroy(col.gameObject);//ボール消滅
		//GameOverの文字を表示させる
		gameOver.Lose();
		goTitle = true;//Update文の実行
	} 
//********** 開始 **********//
	void OnTriggerEnter (Collider col)
	{
		if (col.tag == "Item") {
			Destroy(col.gameObject);
		}
	}
//********** 終了 **********//
}

BottomScript.cs


OnTriggerEnterでタグがItemのオブジェクトにぶつかった時、オブジェクトを破壊しているだけです〜


⑤結果

f:id:hiyotama:20160312192742j:plain
ブロックを破壊するとアイテムが出現し・・・


f:id:hiyotama:20160312192807j:plain
取得するとバーが伸びる!


以上でブロック崩しでブロックを崩した時に、アイテムを発生させることができるようになりました!

読んで下さいまして、ありがとうございました〜