Unity研究所<Unityによるゲーム開発、映像開発>

Unity初心者おやじが綴るゲームで小遣い稼ぎできるようになるまでのブログ

Unityで作った落ちゲー作り方解説  その2 ブロックの消滅判定

今回は、Unityで作った落ちゲーの作り方解説の二回目

 

ブロックの消滅判定について

 

Google Playに公開した落ちゲー

play.google.com

f:id:Harukichi:20200521230608g:plain

 

では、どのようにして判定してブロックを消しているかについて説明する

 

まずは、ブロックのデータ管理用に、画面内でのブロックの配置に合わせて

横 7 × 縦 10 の二次元の配列を作る

 

これに合わせて、ブロックを消す条件が成立した場合にフラグ(「1」)を設定する配列も用意しておく

後からブロックを消すフェーズに来た際には、この配列を参照してフラグが立っているものを消す

 

◆ブロックデータ管理用の配列のイメージ

f:id:Harukichi:20200531222232p:plain

Blockdata = new int[GyouSize, RetsuSize] {
{0,0,0,0,0,0,0 },
{0,0,0,0,0,0,0 },
{0,0,0,0,0,0,0 },
{0,0,0,0,0,0,0 },
{0,0,0,0,0,0,0 },
{0,0,0,0,0,0,0 },
{0,0,0,0,0,0,0 },
{0,0,0,0,0,0,0 },
{0,0,0,0,0,0,0 },
{0,0,0,0,0,0,0 },
};
Erasedata = new int[GyouSize, RetsuSize];

 

◆処理の流れ

ア ブロックが最下位置まで落下した時に、上記の配列にブロックの番号を書き込む

Blockdata[CurrentGO[i].GetComponent<NumberCtrl>().GetCurrentPosition().y, CurrentGO[i].GetComponent<NumberCtrl>().GetCurrentPosition().x]
= CurrentGO[i].GetComponent<NumberCtrl>().GetNumber();

 

ここだけのコードを見てもわかりづらいが、仕組みとしては、現在落下してきたブロックが最下位置に到達したときに、そのx,y座標を取得して配列のインデックスとして使用し、その位置にブロックの番号を書き込んでいるだけ

 

イ そして、書き込んだ後のブロックを消すための判定だが・・・

大まかな流れとしては

・基準は今落下してきて停止したブロックとする

・行方向(水平方向)に消去の条件のチェック

・列方向(垂直方向)に消去の条件のチェック

 

で今回の場合の消去の条件とは、落下して停止したブロックの隣接する左右、上下のブロックの数字を足し合わせてちょうど10になったら、その10を構成するブロックを消すというものとしている

 

 

ウ 行方向のチェック

コードは下の方に記載した通りだが、行っているのは

落下してきて停止したブロックから順番に左側のブロックのデータを参照していき、隣が「0」なら終了

足して10になれば、消去用のデータ配列に「1」を書き込むというのを一巡行い、さらに基準のブロックから一つ右のブロックを基準として再チェック・・・という形で右にブロックがある限り繰り返すというような処理をしている 

 

◆イメージ 

f:id:Harukichi:20200531232933p:plain

  黄色が落下してきたブロック

  左方向に数字を足していく、上記の場合は

  0,0、1,0、2,0、3,0の位置のブロックは足すと10になるため、

  消去用のデータ配列の該当位置には「1」がセットされる

  

  さらに基準ブロックを0,4に移動して同じチェックを行う

  右端まで繰り返す

 


void GyouCheckLeft(Vector2Int currentpos)
{
 int offset = 1;
 int CheckCounter = Blockdata[currentpos.y, currentpos.x];

 //現在の位置をもとに左側に何回チェックをするかを設定
 for (int i = 0; i < currentpos.x; i++)

 {
  //左の範囲内かを確認
  if (currentpos.x - offset >= 0)
  {
   //左が0でない
   if (Blockdata[currentpos.y, currentpos.x - offset] != 0)
   {
    int result = CheckCounter + Blockdata[currentpos.y, currentpos.x - offset];
    //現在位置と左のオフセット位置の値を加算して、10なら終了


    if (result == 10)
    {
     //消去データをセット
     Erasedata[currentpos.y, currentpos.x] = 1;
     IsDeleteBlock = true;

     for (int r = 0; r < offset; r++)
     {
      Erasedata[currentpos.y, currentpos.x - r - 1] = 1;

     }

     break;
    }
    else if (result < 10)
    {
     //データを加算
     CheckCounter = result;

     //オフセットを加算
     offset++;

    }


   }
   //左が0の場合ループ終了
   else
   {
    break;
   }

  }
  else
  {
   //範囲外のためループ終了
   break;
  }

 }

}

 

//下記の処理にて、上記の処理を右端まで繰り返しチェックしている

void GyouCheck(Vector2Int currentpos)
{

 for (int i = 0; i < RetsuSize - currentpos.x; i++)
 {

  if (Blockdata[currentpos.y, currentpos.x + i] != 0)
  GyouCheckLeft(new Vector2Int(currentpos.x + i, currentpos.y));
 }

}

 

エ 列方向のチェック

行のチェックと同じようなイメージで、落下して停止したブロックの上方向にブロックのデータを確認している

コードは下記の通り

void RetsuCheck(Vector2Int currentpos)
{

 int offset = 1;
 int CheckCounter = Blockdata[currentpos.y, currentpos.x];
 int count = 0;

 

 for (int t = 0; t < GyouSize; t++)
 {

  count += Blockdata[t, currentpos.x];

 }

 //全部足して10より小さいなら処理を終了 無駄を省く

 if (count < 10)
  return;

 
//現在の位置をもとに下側に何回チェックをするかを設定
 for (int i = 0; i < currentpos.y; i++)

 {
  //下の範囲内かを確認
  if (currentpos.y - offset >= 0)
  {
   //下が0でない
   if (Blockdata[currentpos.y - offset, currentpos.x] != 0)
   {
    int result = CheckCounter + Blockdata[currentpos.y - offset, currentpos.x];
    //現在位置と下のオフセット位置の値を加算して、10なら終了
    if (result == 10)
    {
     //消去データをセット
     Erasedata[currentpos.y, currentpos.x] = 1;
     IsDeleteBlock = true;

     for (int r = 0; r < offset; r++)
     {
      Erasedata[currentpos.y - r - 1, currentpos.x] = 1;

     }

     break;
    }
    else if (result < 10)
    {
     //データを加算
     CheckCounter = result;

     //オフセットを加算
     offset++;

    }

   }
   //下が0の場合ループ終了
   else
   {
    break;
   }

  }
  else
  {
   //範囲外のためループ終了
   break;
  }

 }

}

 

今回は、消すブロックの判定と、消去用のデータの書き込みまでについて記載した

次回以降では、実際にどのように消しているかと、消した後下のブロックが消えた場合の処理について触れたいと思う

 

以上

 

Unityで作った落ちゲー作り方解説  その1 ブロックの生成、落下

Unityで作った落ちゲーの作り方解説 その1 

 

前回は初めてGoogle Playに公開した自作アプリの紹介をした

そのアプリはこちら

 

f:id:Harukichi:20200521230608g:plain

 

で、今回はこのゲームの作り方解説のその1として、ブロックの落とし方の制御方法等を中心に解説する

 

〇概要

 ・ゲーム中はブロックの生成⇒落下⇒着地⇒条件がそろえば消去⇒ブロックの生成を繰り返すので、ブロックはある程度の機能を持たせたプレファブ化をしている

 

1 ブロックのプレファブを作成方法

 

ア まず、ブロックについては、下記のような画像を用意

 

f:id:Harukichi:20200525223606p:plain

 

Unityにインポートしたら、このファイルを選択し、InspectorにてTexture TypeをSprite(2D and UI)に設定

 

その後、Sprite Editorボタンを押す

f:id:Harukichi:20200525224342p:plain

 

Sprite Editorにて、ブロックごとにスライスする

f:id:Harukichi:20200525224616p:plain

 

スライスすると、元画像の下の階層に分割された画像が生成される

f:id:Harukichi:20200525230427p:plain

 

 

イ 次に、スライスしたブロックの画像のどれか一つをScene Viewにドラック&ドロップ

 

Hierarchy上に作成されたブロックのオブジェクトを選択

スクリプトファイルを作成してアタッチ

 

下記のような機能をブロック自体に実装する

◇ブロックに持たせた機能

 ①ブロックの生成時のナンバーの設定、ナンバーに合わせた画像の選択

 ②ブロックの落下

 ➂ブロックを消去するときのエフェクト発生、消去

 

 

◆ それぞれの機能の実現方法 スクリプト

①ブロックの生成時のナンバーの設定、ナンバーに合わせた画像の選択

まずは、public 変数として、数字の書いた画像をアタッチするスプライトの配列を定義

 public Sprite sprites;

 

Inspectorにて割り当てる

手順は、Projectフォルダの中からドラック&ドロップ

f:id:Harukichi:20200525230427p:plain

 

f:id:Harukichi:20200525230210p:plain


どの数字のスプライトを割り当てるかは、ブロックの生成後にSetup関数にて番号を指定して設定するようにしており、同時に何番が設定されているかのデータも記憶しておくようにしている

 

スプライトの設定については、SpriteRendererコンポーネントを取得して、先ほど作成したスプライトの配列から指定された番号で割り付けるようにしている

 

  SpriteRenderer sr = GetComponent<SpriteRenderer>();
 sr.sprite = sprites[number];

 

 

②ブロックの落下

これについては、下記の関数にて、指定された位置に移動させているのみ

ゲーム進行中は、進行を管理するスクリプトから、一定の時間ごとにこの関数が呼び出されて、落下が実現される

 

なお、ブロック単位で移動のため、移動するピッチ(BlockStep)は、1個のブロックのサイズ分となるように補正している

public void MovePosition(Vector2Int pos)
{
 if (MoveEnable)
 {
  Position.x = pos.x;
  Position.y = pos.y;

  transform.position = new Vector3(HomePosition.x + Position.x * BlockStep,     

 HomePosition.y + Position.y * BlockStep, 0);

 }

}

 

➂ブロックを消去するときのエフェクト発生、消去

エフェクトについては、アセットストアから無料のエフェクトをダウンロード

ブロックの消去に合わせて、エフェクトのプレファブを生成し、エフェクトの消えるタイミングと合わせてブロックも消去している

ゲームの進行を管理するスクリプトにて消去の条件が成立した時に、下記が呼び出される

 

void DestroyExplosion()
{
 Destroy(Instantiate(Explosion, transform.position, transform.rotation), 0.5f);
 Destroy(gameObject);
}

 

 

最後にブロックのプレファブの主なコードは下記の通り

public class NumberCtrl : MonoBehaviour
{
 public Sprite sprites;
 int Number;
 Vector2Int Position;
 [SerializeField] Vector2 HomePosition=new Vector2(-2.77f,-3.35f); //左下の原点位置
 [SerializeField] float BlockStep = 0.8f;//ブロックの移動距離
 bool MoveEnable = false;

 public GameObject Explosion;

 

//プレハブの生成後の初期化/////////////////////////////////////////////////////
public void Setup(int number,Vector2Int pos)
{
 MoveEnable = true;
 MovePosition(pos);
 SpriteRenderer sr = GetComponent<SpriteRenderer>();
 sr.sprite = sprites[number];
 Number = number+1;

}

 

//ブロックの移動/////////////////////////////////////////////////////

public void MovePosition(Vector2Int pos)
{
 if (MoveEnable)
 {
 Position.x = pos.x;
 Position.y = pos.y;

 transform.position = new Vector3(HomePosition.x + Position.x * BlockStep,    HomePosition.y + Position.y * BlockStep, 0);

 }

}

 

 

//消去時のエフェクト発生/////////////////////////////////////////////////////

void DestroyExplosion()
{
 Destroy(Instantiate(Explosion, transform.position, transform.rotation), 0.5f);
 Destroy(gameObject);
}

//番号の設定/////////////////////////////////////////////////////

public void SetNumber(int number)
{
 SpriteRenderer sr = GetComponent<SpriteRenderer>();
 sr.sprite = sprites[number];
 Number = number + 1;
}

 

 

今日のところはここまで

 

Unityで作った落ちゲー作り方解説 目次

せっかく作ったので、作り方を書き残しておきたいと思う

 

Unityを使い始めた人、落ちゲーの作り方に興味がある方に読んでもらえればと・・・

 

メニュー 予定

1 ブロックの生成、落下

2 ブロックの消滅判定

3 ブロックの操作

4 モードセレクト

5 広告掲載

6 参考にした書籍、HPなど

 

今回は以上

Unityで落ちげー作って、Google Playに公開したってよ!!

祝!!

 

とうとうUnityで作った自作アプリをGoogle Playに公開しました!!

 

今年のノルマ達成!!

 

以上

 

 

(-_-メ)

 

 

いや、せっかくなので今回は作ったアプリの紹介をする

 

なお、自体以降では作り方の公開を予定しているので、楽しみにしてもらえると・・

 

Google Playリンク

https://play.google.com/store/apps/details?id=com.YsMfc.AddittoTen

 

では

f:id:Harukichi:20200521230608g:plain

 

(-_-メ)

 

数字が書かれたブロックが落ちてくるので、縦、横隣接したブロックの数字が足して10になるように並べて消すという単純なルール

 

のなかで、やっぱり連続して消せると楽しいよね~っというところがポイント

 

ただし、足して10にすることを常に意識しながらなので、連続させるには戦略要素もあり、結構脳トレになるのではないかと・・・

 

一応、特定の回数の連続(コンボ)を決めると、上級者モードが出現するようにしてみた

少しは遊ぶモチベーションになればと・・・

 

あと、最初は操作するためのボタンも配置していたけれど、スマホらしく

移動・・・左右スワイプ

回転・・・タップ

にしてみた

 

さらに、ハイスコアを表示したり、モード選択もできるようにしたので、このあたりの作り方と

 

落ちげーとしての、ブロックの落とし方、消すための判定の仕方なども公開してしまう予定

 

Google AdMobも実装したのでこれにも触れて

 

Google Playの公開の仕方・・・はほかに譲るかな

 

参考にした書籍、HPなども併せて紹介したい

 

今回のところは以上

 

こうご期待

 

 

 

スマホアプリ開発 その1 ナンバータップ

2020年の目標のスマホアプリリリースに向けた練習 その1

 

ナンバータップというアプリを作ってみたので、今後に残しておきたいTipsを書き残していく

 

f:id:Harukichi:20200126202549g:plain

〇ゲームについて

 やり方は、画面に表示された数字を1から順にタップし、すべて消えるまでのタイムを競うもの

 

〇今回のTips

この中のTipsとして、下記を解説する

①数字のオブジェクトの生成方法

②ナンバーのタップ&消去

 

 

       ①数字のオブジェクトの生成方法 

 ゲームの進行管理をしているスクリプト内で数字のオブジェクトを生成

 f:id:Harukichi:20200126203720p:plain

3行目、4行目

 乱数を利用して画面内にランダムに配置を決める

 InstantiateにてPrefabかされた数字のオブジェクトを、先に決めた位置に生成

 なお、数字のオブジェクトにはRigidBody、およびColliderがついているので、適当な位置に配置しても、互いに反発しあって重ならないように配置される

 

5行目

 数字のオブジェクトに組み込まれている関数にてナンバリングしている

 

 数字のオブジェクトのPrefabに組み込まれている関数

 f:id:Harukichi:20200126203747p:plain

 SpriteRndererを取得して、スプライトとして登録されている丸数字の画像を、配列の中から指定された番号のものに差し替えし、番号も記憶している

 

 

 ②ナンバーのタップ&消去

f:id:Harukichi:20200126203737p:plain

6行目

  Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
    RaycastHit2D hit2d = Physics2D.Raycast((Vector2)ray.origin, (Vector2)ray.direction);

 スマホのタップされた位置を画面の座標に変換

 原点と報告を指定して情報をRaycastHit2D hit2d に保存

 

8行目

 hit2dに書き込まれたゲームオブジェクトの情報から、タグと番号を紹介し、現在消すべき番号のオブジェクトなら、効果音を鳴らしつつ、消滅させている

 

今回はここまで

 

  

 

 

スマホアプリリリースへの道 2020年の目標について

2020年の目標!!!

「今年中にオリジナルのスマホアプリをリリースすること」

とりあえず、上記とする!!

 

 

何か目標がないと、張り合いがないし、モチベーションも上がらないしね・・・

 

現状でも何のためにUnityを勉強しているのかは??

 

興味のあること、いやじゃないことについては、本屋さんで参考書を買ったり、ネットで調べたり、実際に作業したりという作業が苦にならない

 

実際は、この一連の作業は、「勉強」という固めの、避けて通りたくなるようなワードで表されるものではあるが・・

 

好きなことなら関係ないんだよね・・・

 

 

あと、いくつになっても、新しいことができるようになるというのはうれしいもの

上達するということもうれしいもの

 

Unityをかじりだしたのは、こんな感じなのだろうな

興味のあること、いやじゃないことで、できるようになったり、上達したりが感じられやすい

 

つまりは、Unity自体がよくできているからか

 

全く整理できてない(-_-メ)

 

 

いずれにしても、2020年の目標は決めた!!

 

質は問わないが

 

オリジナルのゲームを作る

 

そして、Storeにリリースまでがゴール!!

 

 

今回はここまで、次回より、スマホアプリの作成についてのメモを公開していく

 

 

 

 

 

SpotLightのCookie設定で窓枠の影を落とす

SpotLightを使用した窓からの光、窓枠の影の表現方法

f:id:Harukichi:20200105215729p:plain

 

 

◎用意するもの

 ・Spotlight

 ・窓枠用のテクスチャファイル

f:id:Harukichi:20200105220906p:plain

 

 

①LightをSpotlightで作成し、適当に地面を照らす

f:id:Harukichi:20200105220511p:plain

 

 

②InspectorのCookieの◎ボタンをおして、窓枠用のテクスチャファイルを選択

f:id:Harukichi:20200105220220p:plain

f:id:Harukichi:20200105215744p:plain

 

➂完成形

f:id:Harukichi:20200105221119g:plain

 

テクスチャを変えると、懐中電灯っぽい影も可能!!

f:id:Harukichi:20200105221328p:plain


今日のところはこれにて終了