今回、Unity初心者でありますが、暇つぶしに最適なソリティアを制作したので紹介します。
制作方法を簡単に解説しますので、私と同じぐらいのUnity初心者の方は参考になるかなと思います。
Google Playにも登録出来たので、興味がある人は是非ダウンロードして遊んでみて下さい。
ただし、オリジナリティはゼロであることを始めに言っておきます。
この記事はこんな人におすすめ!
今回、制作したソリティアをWebGL版にしたので遊んでみて下さい。
新しくページを開く場合はこちら。
Google Playにも登録していますので、Androidユーザーの人は下記リンク先からインストールしてみて下さい。
iOS版は無いのでご了承ください。
ソリティア制作方法のポイントを解説していきます。
解説するにあたり、山札、組札、場札という用語が出てきますが、下図の定義とします。
カードの画像を用意して、スプライトエディタで52枚のカード + 裏面に分割し、スプライトを作成します。
①Texture TypeをSprite(2D and UI)に変更。②Sprite ModeをMultipleに変更。③Sprite Editorをクリック。
Sprite Editorで52枚のカード表面とカード裏面に分割し、スプライトを作成。
カードPrefabは、52枚のカードをすべて作成するのではなく、カード裏面のみを作成します。
カードを表面にするときは、スプライトを差し替えるようにします。
52枚のカードがそれぞれどんな状態にあるか記憶するため、スクリプトを追加し、変数を設定します。
カード状態
カードPrefabにEvent Triggerコンポーネントを追加して、カードをクリックしたときの処理を追加します。
Event Triggerの設定方法は、別記事で解説していますので、こちらを参照下さい。
https://craft-gogo.com/unity-doubleclick/
カードを3枚めくります。
一番上のカードかつ裏であれば表にします。
マウスクリック前の位置を記憶した後、下に繋がっているカードすべてを移動させます。
移動中のカードを、マウスボタンを離した場所に移動完了させます。
移動中のカードを、マウスボタンを離した場札列に移動完了させます。
移動中のカードを、マウスボタンを離した場所に移動完了させます。
以上、私がUnityで制作したソリティアの紹介でした。
オリジナリティはゼロですが、ソリティアとしては立派に完成させていますので、暇つぶしにはなると思います。私も電車で移動中などは、自分で作ったソリティアで遊んでいます。
Google Playにも登録出来たので、興味がある人は是非ダウンロードして遊んでみて下さい。
]]>Unityでテトリス風落ちゲーを作ってみたいけど、何から手を付けていいか分からない。私もそんな一人です。ここでは、自分の勉強も含めて、簡単なテトリス風落ちゲーを制作していく過程を掲載していきます。
この連載を最後まで読めば、このようなテトリス風落ちゲーが1人で作れるようになります。
別ウィンドウで開く場合はこちら
最終回はベストスコアセーブ編です。
前回記事では、タイトル画面を追加し、ゲームオーバーになったらタイトル画面に戻れる機能を追加しました。
今回はベストスコアを更新したらセーブし、ゲームを再開時にベストスコアをロードする機能を追加します。
尚、データのセーブ、ロード方法は別記事で詳しく解説していますので、本記事では簡単に説明させてもらいます。
https://craft-gogo.com/unity-datasave/
この記事はこんな人におすすめ!
本ゲーム制作方法は自己流です。もっと簡単に作る方法もあると思いますので、ご了承下さい。
まず、ベストスコアをゲーム画面上に表示させるため、テキストオブジェクトを追加します。
下図のようにベストスコアを表示させましょう。細かな設定は、これまで解説していますので割愛します。
GameController.csにテキスト変数を追加してテキスト変更をスクリプトで扱えるようにします。
public Text bestScoreText;
Unityに戻ってGameControllerコンポーネントにBest Score Textオブジェクトをセットします。
まず、JSON形式でベストスコアを格納するクラスを作成します。
[System.Serializable]
class SaveData
{
public int bestScore;
}
ベストスコアをロードするためのメソッドです。このメソッドを呼び出すことによって、savefile.jsonにセーブされているベストスコアをロードします。
private void LoadBestScore()
{
string path = Application.persistentDataPath + "/savefile.json";
if (File.Exists(path))
{
string json = File.ReadAllText(path);
SaveData data = JsonUtility.FromJson<SaveData>(json);
bestScore = data.bestScore;
}
else
{
bestScore = 0;
}
bestScoreText.text = "Best Score: " + bestScore;
}
スコアがベストスコアを上回ったらJSON形式でスコアを保存します。
private void SaveBestScore(){
if(score > bestScore)
{
bestScoreText.text = "Best Score: " + score;
SaveData data = new SaveData();
data.bestScore = score;
string json = JsonUtility.ToJson(data);
File.WriteAllText(Application.persistentDataPath + "/savefile.json", json);
}
}
Application.persistentDataPathの場所は、Windowsだと\usr\AppData\LocalLow\CompanyNameになります。
ゲームスタート時に作っておいたLoadBestScore()メソッドを呼び出せば、ベストスコアがロードされます。
void Start()
{
/*
(省略)
*/
LoadBestScore();
/*
(省略)
*/
}
ゲームオーバー時に作っておいたSaveBestScore()メソッドを呼び出しましょう!
void Update() {
switch(gameStat){
/*
(省略)
*/
case GAMEOVER:
SaveBestScore();
gameOverText.gameObject.SetActive(true);
restartButton.gameObject.SetActive(true);
returnTitleButton.gameObject.SetActive(true);
break;
}
/*
(省略)
*/
}
ゲームオーバー時にベストスコアが更新されました。
最終回では、ベストスコアを更新したらセーブし、ゲームを再開時にベストスコアをロードする機能を追加しました。
データのセーブ、ロード方法は簡単に説明しましたが、別記事で詳しく解説していますので参考に。
https://craft-gogo.com/unity-datasave/
最後までお読み頂きありがとうございました。
]]>Unityで、オブジェクトダブルクリック時の処理を追加しようとしても、どうしたらよいのか困っていませんか。Event Triggerでシングルクリックはあるけど、ダブルクリックが無い・・・。
今回の記事では、オブジェクトをダブルクリックしたときに色を変更するサンプルを作りながら、Event Triggerにダブルクリックを追加する方法を解説します。
こんな人におすすめ!
まず初めに行うことがEvent Systemオブジェクトを追加することです。
Event Systemは、マウスクリックやディスプレイタッチしたときに、オブジェクトへイベントを送信するのを管理してくれます。
Hierarchyウィンドウから「UI」 > 「Event System」をクリックしましょう。
設定はデフォルトのままで大丈夫です。
次にゲーム画面でオブジェクトをクリックしたときにイベントが発生出来るよう、Main CameraにPhysics 2D Raycasterコンポーネントを追加します。
Physics 2D Raycasterは画面クリックした位置から光線を発し、衝突したオブジェクトにメッセージを送信する役割です。オブジェクトが衝突を検知することによって、オブジェクトがクリックされたことが分かります。
InspectorウィンドウでAdd Componentボタンをクリックし、Physics 2D Raycasterコンポーネントを追加しましょう。
これも設定はデフォルトでOK。
続いてダブルクリックされるオブジェクトの設定に移ります。適当な2Dオブジェクトをまず追加しましょう。
ダブルクリック判定作成の流れは、次のようになります。
Physics 2D Raycasterからの光線と衝突したのを検知出来るようColliderを追加します。
Add Componentボタンをクリックし、Box Collider 2Dコンポーネントを追加しましょう。
設定はデフォルトのままでよいです。
Colliderが衝突を検知したときにイベントを発生出来るようEvent Triggerを追加します。
Add Componentボタンをクリックし、Event Triggerコンポーネントを追加。
「Add New Event Type」> 「PointerDown」を選択して下さい。
PointerDownの処理は後から追加するので、ここでは保留。
PointerDownで発生させる処理をスクリプトで書いていきます。
ダブルクリックされるオブジェクトにスクリプトを追加し、以下のようにコードを書きます。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class DoubleClick : MonoBehaviour
{
private int clickCount;
private bool flg;
void Start()
{
clickCount = 0;
flg = false;
}
public void OnClickDown()
{
clickCount++;
Invoke("OnDoubleClick", 0.3f);
}
private void OnDoubleClick()
{
if(clickCount != 2) {clickCount = 0; return;}
else {clickCount = 0;}
if(flg == false) {
gameObject.GetComponent<SpriteRenderer>().color = Color.red;
flg = true;
}
else
{
gameObject.GetComponent<SpriteRenderer>().color = Color.white;
flg = false;
}
}
}
OnClickDownメソッドはPointer Downに登録するメソッドです。OnClickDownが呼び出されたらclickCountをインクリメントします。そしてOnDoubleClickメソッドを0.3秒後に呼び出します。この時間はダブルクリックの時間間隔パラメータですので、適当に調整してもらって構いません。
OnClickDownが呼び出されたときにclickCountが2回のときにダブルクリックと判定し、処理を実行します。今回は、ダブルクリックされたときにオブジェクトの色を赤に変える処理を追加しました。
スクリプトが出来上がったのでPointer DownにOnClickDownメソッドを登録します。
以上でダブルクリック判定の出来上がり!
ゲームを開始したときはオブジェクトは白です。
オブジェクトの上でダブルクリックすると
オブジェクトが赤色に!
オブジェクトをダブルクリックしたときに色を変更するサンプルを作りながら、Event Triggerにダブルクリックを追加する方法を解説しました。
正直、Unityにダブルクリックを判定する機能が無いのが残念です。(私が知らないだけかもしれません)
今後機能が追加されることを期待します。
最後までお読み頂きありがとうございました。
]]>Unityでテトリス風落ちゲーを作ってみたいけど、何から手を付けていいか分からない。私もそんな一人です。ここでは、自分の勉強も含めて、簡単なテトリス風落ちゲーを制作していく過程を掲載していきます。
この連載を最後まで読めば、このようなテトリス風落ちゲーが1人で作れるようになります。
別ウィンドウで開く場合はこちら
今回はタイトル画面追加編です。
前回記事では、最上位列までブロックが積みあがったらゲームオーバーになる機能を追加しました。
今回は、次の機能を追加します。
この記事はこんな人におすすめ!
本ゲーム制作方法は自己流です。もっと簡単に作る方法もあると思いますので、ご了承下さい。
最初にゲームシーンを移動する方法について解説します。各ゲームシーンにはindexが割り当てられています。確認するには「File > Build Settings」を選択して下さい。
Scenes In Buildの右端の数字が各ゲームシーンのindexです。
ゲームシーンを移動するには、SceneManagement名前空間が必要です。usingで追加し、SceneManager.LoadSceneメソッドでゲームシーンを移動します。引数に先ほど調べたゲームシーンのindexを設定することで、指定したindexのゲームシーンに移動することが出来ます。
using UnityEngine.SceneManagement;
SceneManager.LoadScene(0);
タイトル画面を作っていきましょう。ScenesフォルダにTitleSceneを作成します。
タイトルテキストとスタートボタンを加えます。
タイトルテキストとスタートボタンの文字大きさ、テキスト、配置を設定しましょう。
こんな感じです。
GameSceneのindexを設定するため、「ファイル > Build Settings」を選択し、
TitleSceneのindexを「0」、GameSceneのindexを「1」にします。
次にGameSceneに移動するスクリプトを作成します。GameStartButton.csを作成し、下のメソッドを作成しましょう。GameSceneのindexは「1」なので、LoadSceneメソッドの引数は「1」に設定します。
public void OnGameStartButtonClick()
{
SceneManager.LoadScene(1);
}
GameStartButtonスクリプトをStartButtonオブジェクトのコンポーネントに加えます。
Start ButtonオブジェクトのButtonコンポーネントに自オブジェクトをセットします。
ボタンがクリックされたときの動作を「OnGameStartButtonClick()」に設定します。
これでGameStartボタンをクリックすると、GameSceneに移動し、ゲームが開始されます。
ゲームオーバーになった時、ゲームが中断したままになっていましたので、リスタート機能を追加します。GameSceneからリスタートする「RestartButton」とTitleSceneに戻ってリスタートする「ReturnTitleButton」2つのボタンを追加しました。
こんな感じ。このままだと、GameSceneに移動したときにボタンが表示されていますので、オブジェクトは非表示にしておきます。
GameController.csでこの2つのボタン設定を扱えるよう
public Button restartButton;
public Button returnTitleButton;
追記し、2つのボタンオブジェクトを下図のようにGameControllerスクリプトコンポーネントに設定します。
ゲームオーバーになった時は、リスタートボタンが表示されるようGameController.csに以下追記し、アクティブにします。
void Update() {
switch(gameStat){
/*
(省略)
*/
case GAMEOVER:
gameOverText.gameObject.SetActive(true);
restartButton.gameObject.SetActive(true);
returnTitleButton.gameObject.SetActive(true);
break;
}
/*
(省略)
*/
}
GameController.csでもSceneMangement名前空間を使用するので、以下先頭に追加します。
using UnityEngine.SceneManagement;
タイトル画面に戻るメソッドを作成し、
public void OnReturnTitleButtonClick()
{
SceneManager.LoadScene(0);
}
ReturnTitleButtonのButtonコンポーネントにセットします。
これでタイトル画面に戻るボタンを押したらタイトル画面に戻れます。
「Restart」ボタンが押されたときに動作させるメソッドを作成します。
public void OnRestartButtonClick()
{
gameOverText.gameObject.SetActive(false);
restartButton.gameObject.SetActive(false);
returnTitleButton.gameObject.SetActive(false);
NextBlockSet();
setStart();
}
ゲームオーバー時に表示されたテキスト、ボタンを非表示にします。そして、ゲーム開始時の状態に戻します。
setStart()メソッドは下記の通りです。
private void setStart()
{
gameStat = START;
fallCountTime = 0;
groundCountTime = 0;
downIhbFlg = false;
score = 0;
ResetBlock();
}
private void ResetBlock(){
for(int i=1; i<11; i++){
for(int j=0; j<18; j++){
blockStat[j, i] = 0;
}
}
}
今回は、まずタイトル画面を追加し、Game Startボタンを押したら、ゲームを開始するようにしました。次にゲームオーバーになったら、タイトルに戻るかゲームをやり直すか選択出来るようにしました。
ゲームの完成まであと少しです。
次回はハイスコアを記録し、セーブする機能を追加したいと思います。
https://craft-gogo.com/unity-first-puzzlegame11/
最後までお読み頂きありがとうございました。
]]>Unityでゲームデータをセーブし、次のゲーム開始時にデータをロードしたいと悩んでいませんか?
今回は、JsonUtilityというクラスを使ってJSON形式でデータをセーブ、ロードする方法について解説します。
この記事は
っていう方に読んでもらいたいです。
ここでは、簡単な仕組みをUnityで作りながら解説していきます。
現在スコアがハイスコアより高かったときにハイスコアを更新し、セーブ。ゲーム再開時にハイスコアをロードするといった仕組みです。
それでは、始めましょう!
何を言っているんだ~と思った方は、実際の例を見て下さい。
{"bestName":"Steve","bestScore":1500}
基本的には{ }内に 変数名: 値 と記述していくフォーマットです。
今回はこれだけの知識で十分です。
JSONについてもっと詳しく知りたいと思われた方はGoogle先生で調べてみて下さい。
変数をJSON形式に変換するのは面倒くさいと思われた方。安心して下さい。
UnityにはJsonUtilityというクラスが備わっています。このクラスを使えば、簡単にデータをJSON形式に変換することができます。
using System.IO;
をスクリプト先頭に記述し、
JsonUtility.ToJson() // JSON形式へ変換
JsonUtility.FromJson<>(); // JSON形式から変換
JsonUtility.ToJson()を使えば、変数をJSON形式へ変換。JsonUtility.FromJson<>()を使えばJSON形式から変数に変換できます。
現在スコアがハイスコアより高かったときにハイスコアを更新しセーブ、ゲーム再開時にハイスコアをロードするといった仕組みを作りながら、データセーブ/ロード方法について解説していきます。
まず初めに、Unity上でUIを作成していきます。下図のように現在スコアを入力、ベストスコアを表示するUIを作成して下さい。レイアウトやデザインはお好みで。
次にInputField入力、Text表示をスクリプト上から行えるようにします。
MainManager.csというスクリプトファイルを作成し、下の記述を追加します。
public InputField currentNameIF;
public InputField currentScoreIF;
public Text bestNameText;
public Text bestScoreText;
空のオブジェクトを作り、MainManagerと名称を変更した後、先ほど作成したMainManager.csをコンポーネントに追加します。下のようにスクリプトで作成した変数にTextオブジェクト、Input Fieldオブジェクトを設定しましょう。
これでスクリプト上からInputField入力、Text表示を扱えるようになります。
始めにJSON形式でセーブするデータを格納するクラスを作成します。
[System.Serializable]
class SaveData
{
public string bestName;
public int bestScore;
}
クラスの前に記述した[System.Serializable]は、クラスデータをJSON形式に変換する際に必要となります。
次にSETボタンをクリックしたときに現在スコアがハイスコアを上回っていたら、名前とハイスコアを更新し、これらをJSON形式で保存するメソッドを作成します。
public void OnSetButtonClicked(){
string currentName;
int currentScore;
currentName = currentNameIF.text;
currentScore = int.Parse(currentScoreIF.text);
if(currentScore > bestScore)
{
bestNameText.text = "Name: " + currentName;
bestScoreText.text = "Score: " + currentScore;
SaveData data = new SaveData();
data.bestName = currentName;
data.bestScore = currentScore;
string json = JsonUtility.ToJson(data);
File.WriteAllText(Application.persistentDataPath + "/savefile.json", json);
}
}
JsonUtility.ToJson()は、JSON形式に変換する記述です。
File.WriteAllText()は第1引数で指定されたファイルに第2引数で指定された変数を書き込みます。
Application.persistentDataPathの場所は、Windowsだと\usr\AppData\LocalLow\CompanyNameになります。
データセーブする仕組みを実装したので、次はデータロードする仕組みです。
ゲーム再開したら、セーブしたデータをロードしたいので、Start()メソッドにデータロードスクリプトを記述していきます。
void Start(){
string path = Application.persistentDataPath + "/savefile.json";
if (File.Exists(path))
{
string json = File.ReadAllText(path);
SaveData data = JsonUtility.FromJson<SaveData>(json);
bestName = data.bestName;
bestScore = data.bestScore;
}
else
{
bestName = "";
bestScore = 0;
}
bestNameText.text = "Name: " + bestName;
bestScoreText.text = "Score: " + bestScore;
}
Application.persistentDataPathのsavefile.jsonファイルをFile.ReadAllTextで読み込みます。
読み込んだJSON形式のデータをJsonUtility.FromJson<>()でSaveDataクラスの形式に変換します。
そして、ベストスコアと名前をゲーム画面に表示するといった流れです。
Buildして実行してみましょう。
CurrentのNameとScoreに入力し、SETボタンを押して下さい。BestのScoreよりCurrent Scoreが高ければ、BestのName、Scoreが更新されます。ゲームを中断し、再開してもBestのNameとScoreはゲーム中断前の情報が保持されているはずです。
JsonUtilityというクラスを使ってJSON形式でデータをセーブ、ロードする方法について簡単な仕組みを作りながら解説しました。
現在スコアがハイスコアより高かったときにハイスコアを更新しセーブ。ゲーム再開時にハイスコアをロードするといった仕組みです。
作成方法おさらい
データをセーブ、ロードはゲーム制作の基本ですね。
最後までお読み頂きありがとうございました。
]]>Unityでテトリス風落ちゲーを作ってみたいけど、何から手を付けていいか分からない。私もそんな一人です。ここでは、自分の勉強も含めて、簡単なテトリス風落ちゲーを制作していく過程を掲載していきます。
この連載を最後まで読めば、このようなテトリス風落ちゲーが1人で作れるようになります。
別ウィンドウで開く場合はこちら
今回はゲームオーバー機能追加編です。
前回記事では、消去列数に応じてスコアを加算する仕組みを作りました。
今回は、最上位列までブロックが積みあがったらゲームオーバーになる機能を追加します。
この記事はこんな人におすすめ!
本ゲーム制作方法は自己流です。もっと簡単に作る方法もあると思いますので、ご了承下さい。
まず、ゲーム画面にGame Overと表示させるため、テキストオブジェクトを追加します。
HierarchyウィンドウからUI > Textを選択し、テキストオブジェクトを作成しましょう。名称をGameOver Textに変更します。
Textコンポーネントの設定を下図のように変更しましょう。
Sceneウィンドウには、下図のようにGame Overのテキストが表示されます。
ゲーム開始時にはGame Overのテキストは非表示にしますので、下図のチェックボックスをオフにします。
続いて、スクリプト上からGameOver Textオブジェクトを操作出来るようにします。
GameControllerスクリプトにText型の変数を宣言します。
public Text gameOverText;
Game ControllerコンポーネントにgameOverText変数が追加されますので、GameOver Textオブジェクトをドラッグします。
これでスクリプト上からGameOver Textを操作出来ます。
最上位列がブロックで埋まったらゲームオーバーと判定するメソッドを作成します。
GameControllerスクリプトを開いて下さい。
下記メソッドを追記します。
private bool JudgeGameOver()
{
if(blockStat[fallBlockInitPosY, fallBlockInitPosX] == 3)
{
return true;
}
else
{
return false;
}
}
落下ブロックの初期位置が配置ブロック(=3)の時にJudgeGameOverはtrueを返します。
JudgeGameOverメソッドを使ってゲームオーバーの時にゲーム画面上に”Game Over”と表示させます。
状態遷移図を基に、GROUND状態のときにJudgeGameOverメソッドによってゲームオーバーを判定します。ゲームオーバーと判定したら、GAME OVER状態に遷移し、GameOver Textオブジェクトをアクティブにします。ここでも状態遷移図を作っておくとプログラムを書くのが楽ちんですね。
GameControllerスクリプトのUpdateメソッドに上記処理を追加します。
void Update() {
switch(gameStat){
case START:
/* (省略) */
break;
case GROUND:
/* (省略) */
// 落下ブロックの着地確定
if(groundCountTime >= 1){
/* (省略) */
// 1列以上ブロックが揃ったら"ERASE"に遷移
if(JudgeEraseRow()){
gameStat = ERASE;
}
// 最上位までブロックが積みあがったら"GAMEOVER"に遷移
else if(JudgeGameOver()){
gameStat = GAMEOVER;
}
else
{
NextBlockSet();
gameStat = START;
}
}
break;
case ERASE:
/* (省略) */
break;
case GAMEOVER:
gameOverText.gameObject.SetActive(true);
break;
}
}
最上位列までブロックが積みあがったらゲーム画面にGame Overと表示されるようになりました!
今回はゲームオーバー機能追加編として、最上位列までブロックが積みあがったらゲームオーバーになる機能を追加しました。
作り方をおさらいすると
です。
次回は、タイトル画面を作り、シーンを遷移させる機能を追加していきたいと思います。
https://craft-gogo.com/unity-first-puzzlegame10/
最後までお読み頂きありがとうございました。
]]>Unityでテトリス風落ちゲーを作ってみたいけど、何から手を付けていいか分からない。私もそんな一人です。ここでは、自分の勉強も含めて、簡単なテトリス風落ちゲーを制作していく過程を掲載していきます。
この連載を最後まで読めば、このようなテトリス風落ちゲーが1人で作れるようになります。
別ウィンドウで開く場合はこちら
今回はスコア加算編です。
前回記事では、1列ブロックが揃ったのを判定し、ブロックを消去するまでのプログラムを解説しました。
今回は、消去列数に応じてスコアを加算する仕組みを作っていきます。
この記事はこんな人におすすめ!
本ゲーム制作方法は自己流です。もっと簡単に作る方法もあると思いますので、ご了承下さい。
まず、ゲーム画面上にスコアを表示するテキストオブジェクトを追加します。
HierarchyウィンドウからUI > Textを選択して下さい。
Canvasオブジェクトが出来、その下にTextオブジェクトが追加されます。名前をScore Textに変更しましょう。
次にInspectorウィンドウ TextコンポーネントのText、Font Size、Colorを下図のように変更します。
続いてSocre Textオブジェクトをゲーム画面左上に配置します。
Inspectorウィンドウ Rect TransformコンポーネントのAnchor Presetsを選択し、Altキーを押しましょう。すると、下図のような表示から
下図の表示に変わります。四角で囲まれた箇所をクリックして下さい。
Score Textオブジェクトがゲーム画面の左上に配置されました。
ここでは、消去列に応じてスコアを加算するメソッドを作成していきます。
GameControllerスクリプトを開いて、下のAddScoreメソッドを追加して下さい。
private int AddScore(int rowNum)
{
int addScore;
if(rowNum == 1){
addScore = 10;
}
else if(rowNum == 2){
addScore = 30;
}
else if(rowNum == 3){
addScore = 80;
}
else if(rowNum == 4){
addScore = 200;
}
else{
addScore = 0;
}
return addScore;
}
引数を消去列、戻り値を加算スコアとしています。1列揃ったら10点、2列揃ったら30点、3列揃ったら80点、4列揃ったら200点としました。
Score TextオブジェクトのTextをGameControllerスクリプト上から変更出来るように、以下をスクリプト先頭に追加します。
using UnityEngine.UI;
次にscoreText変数、score変数を追加します。
public Text scoreText;
private int score;
Unityに戻るとGame ControllerオブジェクトのGameControllerコンポーネントにscoreText変数が追加されますので、Score Textオブジェクトをドラッグします。
これでGameControlleスクリプト上からScore TextオブジェクトのTextを変更する準備が整いました。
では、消去列に応じた点数をscoreに加算し、scoreTextに反映するスクリプトを作成していきます。
まず、前回のブロック消去編で作成したBlockEraseメソッドを修正します。
消去列数eraseCountを戻り値として返すようにしました。
private int BlockErase(){
int eraseCount;
/*
(省略)
*/
return eraseCount;
}
eraseCountをAddScoreメソッドの引数とし、消去列数に応じた点数をscoreに加算します。そして、scoreTextにscoreを反映させます。
void Update() {
switch(gameStat){
/*
(省略)
*/
case ERASE:
int n;
n = BlockErase();
score += AddScore(n);
scoreText.text = "SCORE: " + score;
NextBlockSet();
gameStat = START;
break;
}
}
1列揃ったらゲーム画面左上に、消去列数に応じて加算されたスコアが表示されます。
消去列数に応じてスコアを加算する仕組みを作りました。
今回以下を解説しました。
次回は最上位列までブロックが埋まったらゲームオーバーする仕組みを作っていく予定です。
https://craft-gogo.com/unity-first-puzzlegame9/
最後までお読み頂きありがとうございました。
]]>Unityでテトリス風落ちゲーを作ってみたいけど、何から手を付けていいか分からない。私もそんな一人です。ここでは、自分の勉強も含めて、簡単なテトリス風落ちゲーを制作していく過程を掲載していきます。
この連載を最後まで読めば、このようなテトリス風落ちゲーが1人で作れるようになります。
別ウィンドウで開く場合はこちら
今回はブロック消去編です。
前回記事では、落下ブロックが着地したら、配置ブロックへ変換させるプログラムを作成しました。
今回は、 1列ブロックが揃ったのを判定し、ブロックを消去するまでのプログラムを解説します。
この記事はこんな人におすすめ!
本ゲーム制作方法は自己流です。もっと簡単に作る方法もあると思いますので、ご了承下さい。
まず、1列すべてブロックが揃った列を検索して、列を消去するかどうか判定するメソッドを作成します。
private bool JudgeEraseRow()
{
bool eraseFlg = false;
for(int j=0; j<18; j++){
eraseRow[j] = false;
bool buff = true;
for(int i=1; i<11; i++){
if(blockStat[j,i] != 3)
{
buff = false;
}
}
if(buff == true){
eraseRow[j] = true;
eraseFlg = true;
}
}
return eraseFlg;
}
戻り値として、bool型のeraseFlgを返し、trueであれば1列以上ブロックが揃っていることになります。
bool型の配列eraseRowは、何列目が揃ったかの情報を格納します。
揃った列のブロックを消去して下に詰めるプログラムの解説です。
private void BlockErase(){
int i,j,k;
int eraseCount;
eraseCount = 0;
for(j=0; j<18; j++){
if(eraseRow[j] == true){
eraseCount++;
// 1行消去
for(i=1; i<11; i++){
blockStat[j, i] = 0;
}
// 消去分、下にずらす
for(k=j; k>0; k--){
for(i=1; i<11; i++){
blockStat[k, i] = blockStat[k-1, i];
blockStat[k-1, i] = 0;
}
}
}
}
}
最上位からブロックが揃った列を探索していき、揃った列を見つけたら、その列すべてのブロック状態を、「3」から「0」に変換します。
そして、消去した列より上の列を1マスずつ下にずらします。
前回までは、ブロックのゲーム画面表示をUpdate()内に記述していましたが、配置ブロックもUpdate()内に記述すると見通しが悪くなるので、メソッド化しました。
private void UpdateDisplay()
{
// 落下ブロックのゲーム画面表示
for(int i=0; i<4; i++){
for(int j=0; j<4; j++){
Destroy(fallBlockObj[j,i]);
if(fallBlockStat[j,i] == 2){
fallBlockObj[j,i] = Instantiate(fallBlockPfb, new Vector3(fallBlockPosX + i + OX, -fallBlockPosY -j + OY, 0), Quaternion.identity);
}
}
}
// 配置ブロックのゲーム画面表示
for(int i=1; i<11; i++){
for(int j=1; j<18; j++){
Destroy(blockObj[j,i]);
if(blockStat[j,i] == 3){
blockObj[j,i] = Instantiate(placementBlockPfb, new Vector3(i + OX, -j + OY, 0), Quaternion.identity);
}
}
}
}
ゲーム設計編で作成した状態遷移図を基に、”GROUND”状態時に消去判定し、ブロックが1列以上揃ったばあいに”ERASE”状態に遷移させます。
状態遷移図があると、プログラム作成がすいすい進みます。設計は大事ですね。
void Update() {
switch(gameStat){
case START:
/*
(省略)
*/
case GROUND:
/*
(省略)
*/
// 落下ブロックの着地確定
if(groundCountTime >= 1){
/*
(省略)
*/
// 1列以上ブロックが揃ったら"ERASE"に遷移
if(JudgeEraseRow()){
gameStat = ERASE;
}
else
{
NextBlockSet(); // 次の落下ブロックをセット
gameStat = START;
}
}
break;
case ERASE:
BlockErase(); // 揃った列のブロックを消去し、1列下に詰める
NextBlockSet(); // 次の落下ブロックをセット
gameStat = START;
break;
case GAMEOVER:
break;
}
/*
(省略)
*/
UpdateDisplay();
}
ブロックが1列揃ったらブロックが消えるようになりました。かなりゲームになってきました!
今回は、 1列ブロックが揃ったのを判定し、ブロックを消去するまでのプログラムを解説しました。
次回は、ブロックが1列揃ったら得点を増やし、ゲーム要素を追加していく予定です。
https://craft-gogo.com/unity-first-puzzlegame8/
最後までお読み頂きありがとうございました。
]]>Unityでテトリス風落ちゲーを作ってみたいけど、何から手を付けていいか分からない。私もそんな一人です。ここでは、自分の勉強も含めて、簡単なテトリス風落ちゲーを制作していく過程を掲載していきます。
この連載を最後まで読めば、このようなテトリス風落ちゲーが1人で作れるようになります。
別ウィンドウで開く場合はこちら
今回はブロック配置編です。
前回記事では、落下ブロックの当たり判定を作成し、落下ブロックが壁ブロックに接触した際の移動を拘束するプログラムを作成しました。更に壁ブロックに着地すると、次の落下ブロックが落ちてくるようにしました。
今回は、 落下ブロックが着地したら、配置ブロックへ変換させるプログラムの解説をします。
この記事はこんな人におすすめ!
本ゲーム制作方法は自己流です。もっと簡単に作る方法もあると思いますので、ご了承下さい。
落下ブロックが着地確定したら、落下ブロックを配置ブロックに変換します。配置ブロックの状態は「3」と定義しましたので、落下ブロックが着地した位置のブロック状態を「3」にします。
その後、次の落下ブロックを初期位置にセットし、落下開始させます。
void Update() {
switch(gameStat){
case START:
/*
(省略)
*/
break;
case GROUND:
/*
(省略)
*/
if(groundCountTime >= 1){
// 落下ブロックを配置ブロックに変換
for(int i=0; i<4; i++){
for(int j=0; j<4; j++){
if(fallBlockStat[j,i] == 2){
blockStat[j +fallBlockPosY, i +fallBlockPosX] = 3;
}
}
}
// 次の落下ブロックを初期位置にセットし、落下開始
fallBlockPosX = fallBlockInitPosX;
fallBlockPosY = fallBlockInitPosY;
blockNum = Random.Range(0, 8);
rot = 0;
fallBlockStat = fallBlockSet.set(blockNum, rot);
gameStat = START;
groundCountTime = 0;
}
break;
case ERASE:
break;
case GAMEOVER:
break;
}
}
ゲーム画面に配置ブロックを表示させます。配置ブロックPrefabをブロック状態が「3」の位置にセットします。
public GameObject placementBlockPfb; // 配置ブロックPrefab
void Update() {
// 配置ブロックの画面表示
for(int i=1; i<11; i++){
for(int j=1; j<18; j++){
Destroy(blockObj[j,i]);
if(blockStat[j,i] == 3){
blockObj[j,i] = Instantiate(placementBlockPfb, new Vector3(i + OX, -j + OY, 0), Quaternion.identity);
}
}
}
}
Unityの画面に戻ったら、Game ControllerコンポーネントのPlacement Block Pfb欄にPlacement Blockをセットしましょう。
今回は落下ブロック配置編として、 落下ブロックが着地したら、配置ブロックへ変換させるプログラム 作成を解説しました。
次回はゲームの肝である、横一列揃ったら消去するプログラムの解説をしていく予定です。
最後までお読み頂きありがとうございました。
https://craft-gogo.com/unity-first-puzzlegame7/
Unityでテトリス風落ちゲーを作ってみたいけど、何から手を付けていいか分からない。私もそんな一人です。ここでは、自分の勉強も含めて、簡単なテトリス風落ちゲーを制作していく過程を掲載していきます。
この連載を最後まで読めば、このようなテトリス風落ちゲーが1人で作れるようになります。
別ウィンドウで開く場合はこちら
今回は当たり判定編です。
本記事は4つの構成で解説していきます。
まだ落下ブロック操作編を読んでない方は、こちらを先に読むことをお勧めします。
この記事はこんな人におすすめ!
本ゲーム制作方法は自己流です。もっと簡単に作る方法もあると思いますので、ご了承下さい。
落下ブロックの着地判定は、落下ブロックの1マス下が壁ブロックまたは配置ブロックの場合に判定するようにします。
各マスの状態は、落下ブロック「2」、壁ブロック「1」、配置ブロック「3」と定義しました。そのため、落下ブロック「2」の1マス下が壁ブロック「1」または配置ブロック「3」であれば、着地と判定させます。
下のjudgeGroundメソッドが落下ブロックの着地判定になります。
public bool judgeGround(int blockNum, int rot, int[,] blockStat, int x, int y){
bool groundFlg = false;
int[,] block = new int[4,4];
block = fallBlockSet.set(blockNum, rot);
for(int i=0; i<4; i++){
for(int j=3; j>=0; j--){
if(block[j,i] == 2){
if(blockStat[y + j + 1, x + i] == 1 || blockStat[y + j + 1, x + i] == 3){
groundFlg = true;
break;
}
}
}
}
return groundFlg;
}
落下ブロックの側面当たり判定は、着地判定と同様、 落下ブロックの1マス右または左が壁ブロックまたは配置ブロックの場合に判定するようにします。
下のjudgeContactRightメソッドが落下ブロックの右側面当たり判定、judgeContactLeftメソッドが左側面当たり判定になります。
public bool judgeContactRight(int blockNum, int rot, int[,] blockStat, int x, int y){
bool contactFlg = false;
int[,] block = new int[4,4];
block = fallBlockSet.set(blockNum, rot);
for(int j=0; j<4; j++){
for(int i=3; i>=0; i--){
if(block[j,i] == 2){
if(blockStat[y + j, x + i + 1] == 1 || blockStat[y + j, x + i + 1] == 3){
contactFlg = true;
break;
}
}
}
}
return contactFlg;
}
public bool judgeContactLeft(int blockNum, int rot, int[,] blockStat, int x, int y){
bool contactFlg = false;
int[,] block = new int[4,4];
block = fallBlockSet.set(blockNum, rot);
for(int j=0; j<4; j++){
for(int i=0; i<4; i++){
if(block[j,i] == 2){
if(blockStat[y + j, x + i - 1] == 1 || blockStat[y + j, x + i - 1] == 3){
contactFlg = true;
break;
}
}
}
}
return contactFlg;
}
落下ブロックの着地判定プログラムが完成したので、着地判定したら一定時間経過後に次の落下ブロックを落とすプログラムを作成していきます。
企画編でゲームの状態遷移を設計しました。
これに則ってプログラムを書いていきましょう。
下のプログラムが 落下ブロックが着地判定したら一定時間毎に落下ブロックを落とすプログラムです。GameControllerスクリプトのStartメソッド、Updateメソッドにプログラムを追加します。既に説明した内容については省略していますので、 ご了承を。
private int gameStat; // ゲームステータス
private const int GAMEOVER = 0;
private const int START = 1;
private const int GROUND = 2;
private const int ERASE = 3;
private bool downIhbFlg; // 0:下移動許可、1:下移動禁止
private float fallCountTime; // 落下ブロックが1マス落下してからの経過時間
private float groundCountTime; // 落下ブロックが着地してからの経過時間
/*
... (省略)
*/
void Start()
{
gameStat = START;
fallCountTime = 0;
groundCountTime = 0;
downIhbFlg = false;
/*
... (省略)
*/
}
void Update()
{
switch(gameStat){
case START:
downIhbFlg = false;
// 落下ブロックを1秒毎に落下
fallCountTime += Time.deltaTime;
if(fallCountTime >= 1){
fallBlockPosY++;
fallCountTime = 0;
}
// 落下ブロックの着地判定
if(judgeGround(blockNum, rot, blockStat, fallBlockPosX, fallBlockPosY) == true){
gameStat = GROUND;
}
break;
case GROUND:
fallCountTime = 0;
groundCountTime += Time.deltaTime;
downIhbFlg = true;
// 落下ブロックの非着地判定
if(judgeGround(blockNum, rot, blockStat, fallBlockPosX, fallBlockPosY) == false){
groundCountTime = 0;
gameStat = START;
}
if(groundCountTime >= 1){
fallBlockPosX = fallBlockInitPosX;
fallBlockPosY = fallBlockInitPosY;
blockNum = Random.Range(0, 8);
rot = 0;
fallBlockStat = fallBlockSet.set(blockNum, rot);
gameStat = START;
groundCountTime = 0;
}
break;
case ERASE:
break;
case GAMEOVER:
break;
}
// 下キー or Sキーを押したとき落下ブロックを1マス下に移動
if(Input.GetButtonDown("Vertical") == true && downIhbFlg == false){
if(Input.GetAxis("Vertical") < -0.01f)
{
fallBlockPosY++;
fallCountTime = 0;
}
}
}
ゲームが開始したら、ゲームステータスを”START”にします。”START”では、落下ブロックの着地判定を行い、判定したら一定時間後にゲームステータスを”GROUND”に遷移させます。”GROUND”では、着地時間を計測し、一定時間経過したら次の落下ブロックを表示させ、”START”状態に戻します。もしプレイヤーが落下ブロックを左右に移動させ、着地判定から抜けたら何もせず”START”状態に戻します。
落下ブロックの側面当たり判定を使って、落下ブロックの横移動を拘束するプログラムを作っていきます。
if(Input.GetButtonDown("Horizontal") == true)
{
// 右キー or Dキーを押したとき落下ブロックを1マス右に移動
if(Input.GetAxis("Horizontal") > 0.01f && judgeContactRight(blockNum, rot, blockStat, fallBlockPosX, fallBlockPosY) == false)
{
fallBlockPosX++;
}
// 左キー or Aキーを押したとき落下ブロックを1マス左に移動
if(Input.GetAxis("Horizontal") < -0.01f && judgeContactLeft(blockNum, rot, blockStat, fallBlockPosX, fallBlockPosY) == false)
{
fallBlockPosX--;
}
}
キー入力で左右移動するプログラムは既に作成済ですので、キー操作判定内に側面当たり判定を追加することで落下ブロックの横移動を拘束させました。
落下ブロックを左右に移動し、側面が壁ブロックに接触した際、左右移動が拘束出来ていることが確認出来ましたね。
更に壁ブロックに着地すると、次の落下ブロックが落ちてくるようになりました。
今回は当たり判定編として以下内容について解説しました。
現状では、落下ブロックが下壁まで落下してもブロックが配置されず、次の落下ブロックが表示されるだけです。次回は、落下ブロックを配置ブロックへ変換させる方法について解説する予定です。
https://craft-gogo.com/unity-first-puzzlegame6/
最後までお読み頂きありがとうございました。
]]>