*

[Unity]Unity2Dチュートリアル 同じ色のパズルを消去する ソース解説

公開日: : C#, Unity, ソース

◆全文

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

public class GameSystem : MonoBehaviour {
	private const int TileLineNum = 5;
	private const int TileColNum = 6;
	private const float TileWidth = 0.5f;
	private const float TileHeight = 0.5f;
	private const float FirstTilePosX = -1.5f;
	private const float FirstTilePosY = -2;

	public GameObject holdObj;
	public float holdPositionX;
	public float holdPositionY;
	private float z = 10f;
	private GameObject[,] tileSet;
	
	// Use this for initialization
	void Start () {
		SetTileSet();
	}
	
	// Update is called once per frame
	void Update () {
		if(Input.GetMouseButtonDown(0)){
			LeftClick();
		}
		if(Input.GetMouseButton(0)){
			LeftDrag();
		}
		if(Input.GetMouseButtonUp(0)){
			LeftUp();
			DeleteMatchTile();
		}
	}
	
	private void LeftClick(){
		Vector3 tapPoint = new Vector3(Input.mousePosition.x, Input.mousePosition.y, z);
		if(holdObj == null){
			Collider2D col = Physics2D.OverlapPoint(Camera.main.ScreenToWorldPoint(tapPoint));
			if(col != null){
				this.holdObj = col.gameObject;
				holdPositionX = this.holdObj.transform.position.x;
				holdPositionY = this.holdObj.transform.position.y;
				holdObj.transform.position = Camera.main.ScreenToWorldPoint(tapPoint);
			}
		}
		
	}
	private void LeftDrag(){
		Vector3 tapPoint = Input.mousePosition;
		if(holdObj != null){
			this.holdObj.transform.position = Camera.main.ScreenToWorldPoint(new Vector3(tapPoint.x, tapPoint.y, z));
			Collider2D[] colSet = Physics2D.OverlapPointAll(Camera.main.ScreenToWorldPoint(new Vector3(tapPoint.x, tapPoint.y, z)));
			if(colSet.Length > 1){
				foreach(Collider2D col in colSet){
					if(!col.gameObject.Equals(this.holdObj)){
						float tmpPositionX = holdPositionX;
						float tmpPositionY = holdPositionY;
						holdPositionX = col.gameObject.transform.position.x;
						holdPositionY = col.gameObject.transform.position.y;
						col.gameObject.transform.position = new Vector3(tmpPositionX, tmpPositionY, z);
					}
				}
			}
		}
	}
	private void LeftUp(){
		if(holdObj != null){
			holdObj.transform.position = new Vector3(holdPositionX, holdPositionY, z);
			holdObj = null;
		}
	}
	private void SetTileSet(){
		GameObject[,] tileSet = new GameObject[TileLineNum,TileColNum];
		for(int i = 0; i < TileLineNum; i++){
			for(int j = 0; j < TileColNum; j++){
				Collider2D col = Physics2D.OverlapPoint(new Vector2(FirstTilePosX + TileWidth * j, FirstTilePosY + TileHeight * i));
				if("tile".Equals(col.tag)){
					tileSet[i,j] = col.gameObject;
				}
			}
		}
		
		this.tileSet = tileSet;
	}

	private void DeleteMatchTile(){
		for(int i = 0; i < TileLineNum; i++){
			for(int j = 0; j < TileColNum - 1; j++){
				try{
					GameObject nowObj = this.tileSet[i,j];
					GameObject nextObj = this.tileSet[i,j+1];
					SpriteRenderer nowRenderer = nowObj.GetComponent<SpriteRenderer>();
					SpriteRenderer nextRenderer = nextObj.GetComponent<SpriteRenderer>();
					Sprite nowSprite = nowRenderer.sprite;
					Sprite nextSprite = nextRenderer.sprite;
					if(nowSprite.Equals(nextSprite)){
						Destroy(nowObj);
						Destroy(nextObj);
					}
				}catch{
				}
			}
		}
	}
}

◆解説

private void DeleteMatchTile(){
	for(int i = 0; i < TileLineNum; i++){
		for(int j = 0; j < TileColNum - 1; j++){
			try{
				GameObject nowObj = this.tileSet[i,j];
				GameObject nextObj = this.tileSet[i,j+1];
				SpriteRenderer nowRenderer = nowObj.GetComponent<SpriteRenderer>();
				SpriteRenderer nextRenderer = nextObj.GetComponent<SpriteRenderer>();
				Sprite nowSprite = nowRenderer.sprite;
				Sprite nextSprite = nextRenderer.sprite;
				if(nowSprite.Equals(nextSprite)){
					Destroy(nowObj);
					Destroy(nextObj);
				}
			}catch{
			}
		}
	}
}

特筆すべきは
SpriteRenderer nowRenderer = nowObj.GetComponent();
上記のようにSpriteRendererを取得して、その後に
Sprite nowSprite = nowRenderer.sprite;
スプライトを取得。
if(nowSprite.Equals(nextSprite)){
そして両方のスプライトを比較して、同じだったらですとろーい。

try~catch句は中でtryのなかでエラー(例外)が起きたときに、catchまで飛ぶ処理です。
今回のどこで例外が起きるかというと、

if(nowSprite.Equals(nextSprite)){
	Destroy(nowObj);
	Destroy(nextObj);
}

この部分で、オブジェクトを破壊してしまっているので、「次にクリックされたときに」ObjectがnullになってしまいMissingReferenceException(参照元のGameObjectが見つからない)が発生してしまうからです。
いまいちDestroyをかけてからのGameObjectの寿命がわからないのですが、ここの判定でぐるぐる回ってる間はまだDestroyされても参照が出来ます。
本来であればnullかどうかの判定を加えるべきですが、わかりやすく、かつtry~catchのご紹介、です。
ちなみにtry~catchは負担のかかる処理ですので、if(obj != null)という判定のほうがコストが下がります。
どのようなものがくるか分かりきっているときは、if文を入れるべきでしょう。

 

[Unity]Unity2Dチュートリアル 同じ色のパズルを消去する へ戻る

ad

関連記事

Unity_

[Unity]Unity2Dチュートリアル 画面上のGameObjectを左下から取得する

前回、画面上のオブジェクトを一括で手に入れる方法はわかりました。 しかし、これではどのオブジェクト

記事を読む

logo

[C#]BinaryFormatterでのDeserializeが遅い。遅すぎる。

概要 BinaryFormatterのサイズ的には大して変わらんとして、じゃあ速度的にはどうなのよ

記事を読む

Delgate Multi Thread

[C#]マルチスレッドとイベントハンドラでデータベースのテーブルの値の変更を検知する。

システム利用中にデータベースの内容が更新 こういったシステムは往々にしてあるかと思います。 特に

記事を読む

unity toggle button label

[Unity]コードリファレンス テキストを表示する。

テキストを表示します。 OnGUI() Unityでテキストを表示する場合は、OnGUI()

記事を読む

logo

[Unity]Unity 2Dチュートリアル スプライトをドラッグ(タップ)して移動する ソース解説

◆全文 using UnityEngine; using System.Collection

記事を読む

logo

[C#,Access]microsoft AccessにODBC接続する

「client AccessのODBC」というタイトルのために、AccessのODBC接続を知りたく

記事を読む

wannabenote_unity

[Unity]コードリファレンス ゲーム時間を表示する。

ゲーム内の時間を表示します。 Timeクラス 時間のためのクラスです。 ゲームが起動してか

記事を読む

logo

[iTextSharp,C#]TifファイルをPDFに変換する。

TifファイルをPDFに変換してほしいと言われて作ったときのソースのメイン部分を抜粋です。 確

記事を読む

wannabenote

[Excel,C#]C#でExcelにデータを一括出力する

大体いつも忘れるこのやり方。 Excelにデータを出力する 方法論 単純な方法ではデータを一行

記事を読む

wannabenote

[C#]マルバツゲームを作ろう

Twitterでお題を出してください、というツイートに脊椎反射でマルバツゲームとか言ってしまったんで

記事を読む

ad

Message

メールアドレスが公開されることはありません。

次のHTML タグと属性が使えます: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code class="" title="" data-url=""> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre class="" title="" data-url=""> <span class="" title="" data-url="">

ad

  •  Auther;わなび

     「オープン系得意だよね? 俺のPCの調子悪いんだけど」という無茶振りから解き放たれゲームエンジニアに。
    C#とかUnityを扱います。
    Twitterフォロー大歓迎です。
    githubアカウント→wannabenote
  • follow us in feedly
PAGE TOP ↑