【Unity】マップエディターを自作してみる(後編)

前回に続き、簡易マップエディターの作成でっす。

筆操作と言っていいのかわからないのですが、
一応、操作系は出来上がりました。

今回は、スプライトの一括クリアとcsvファイル作成を組んで行きます。

まずは、一括クリアからなんですが、
スプライトの貼り付けは、FieldButtonは単体で処理を行っています。

各ボタンにスクリプトを割り当ててるので、ボタン設定などを一つ一つ
設定するのは面倒です。

なので、PalletManagerから各ボタンに指示がだせるように
処理して行こうと思います。

まず、UnityでUIを作ります。
MapTest⑬.jpg
ついでにセーブボタンも作っておきます。

これは、Buttonオブジェクトで問題ないかと。

つづいて、スクリプトを作成します。
PalletManager

private bool Clear; //スプライトをnullにするフラグ変数
private int count; //フィールドボタンのカウント変数

//オールクリアを押した処理
public void AllClear()
{
ACProperty = true;
}

//各ボタンのクリアが出来たかカウントする
public void SignCount()
{
count++;
if (count == 36)
{
ACProperty = false;
count = 0;
}
}

//オールクリア時の指示を各ボタンに送る
public bool ACProperty
{
get{ return Clear; }
set { Clear = value; }
}

説明なんですが、
各ボタンからクリアボタンが押されたか監視して、
クリアボタンが押されたらスプライトを削除すると言う感じで処理します。

クリアボタンにAllClearメソッドを割り当てて、
ボタンを押すとフラグが立ち、ACPropertyにtrueをセットします。

ボタン側でClearフラグが立ったらスプライトを削除させます。
各ボタンがスプライトを削除した所で、PalletManagerにサインを出します。
サインの受け取りには、SignCountメソッドを使います。

SignCountメソッドは、ボタンの数をカウントして、36ボタン全てがクリアされた所で、
ACPropertyにfalseをセットして停止させます。

続いて、FieldButtonを組みます。
FieldButton

private bool ACsign; //オールクリアのフラグ変数

// Update is called once per frame
void Update()
{
SignalCheck();
}

//オールクリアのシグナルを判断する
void SignalCheck()
{
//オールクリアの指示判断
if (palletM.ACProperty && ACsign == false)
{
SpriteClear();
}
//オールクリア後の復旧判断
if (palletM.ACProperty == false && ACsign)
{
ACsign = false;
}
}

//オールクリア時の処理
void SpriteClear()
{
this.gameObject.GetComponent<Image>().sprite = null;
palletM.SignCount();
ACsign = true;
}

判定が少しややこしいですが説明すると…
PalletManagerのフラグがONになった事を確認するのですが、
ACPropertyがtrueの間、SpriteClearメソッドを呼び出し続ける事になります。
なので、一度だけ呼び出す為にACsignのフラグを用意しました。

SpriteClearメソッドを呼び出した後、ACPropertyがfalseになるまでONにしておけば、
一度しか呼び出されなくなります。

全ボタンがサインを出し終わるとACPropertyがOFFになるので、
それを見て、ACsignもOFFにするようにしています。

SpriteClearメソッドは、単純にスプライトの削除とPalletManagerにサインを出しています。

スクリプトが出来たので、クリアボタンにPalletManagerとAllClearメソッドを割り当てます。
動作確認はこちら↓

無事に動いてくれました。(^ё^) ♪♪

ここまで来れば、後はcsvファイルの作成を組んで行きます。

ファイル置き場が必要なので、UnityのResourcesフォルダの中に
MapTest⑭.jpg
DataTextのフォルダを用意します。

続いてスクリプトを作成します。
ここからは、各ボタンのスプライトナンバーを管理していきます。
PalletManager

using System;


private int[] FieldPosition = new int[36]; //各ポジションのスプライトナンバー

//各ポジションのスプライトナンバーを取得
public void SetPosition(int pos)
{
FieldPosition[pos] = SelectSprite;
}

//各ボタンのクリアが出来たかカウントする
public void SignCount()
{
count++;
if (count == 36)
{
Array.Clear(FieldPosition, 0, FieldPosition.Length);
ACProperty = false;
count = 0;
}
}

まず、各フィールドボタンにセットされているスプライトナンバーを
取得する変数を用意します。

スプライトがセットされる度に変数にナンバーを保管するので、
SetPositionメソッドを用意しました。

FieldButton側からポジションを送って、その時のスプライトナンバーを登録します。

オールクリアに対応しないといけないので、
SignCountメソッド内に配列の初期化を設定します。
Arrayを使う場合は、名前空間にSystemを宣言しないとエラーになります。

FieldButton側にSetPositionメソッド呼び出しを追加します。
FieldButton

//フィールドボタンを押した処理
public void PushButton()
{
//マウスがクリックされてなければリターンする
if (Input.GetMouseButton(0) == false)
{
return;
}

//選択中のパレットナンバーからスプライトを取得
if (palletM.SelectProperty == 0)
{
//パレットナンバーが0ならスプライトを削除
this.gameObject.GetComponent().sprite = null;
palletM.SetPosition(PosNum);
}
else
{
//パレットナンバーにあったスプライトを表示する
this.gameObject.GetComponent().sprite = Pattern[palletM.SelectProperty];
palletM.SetPosition(PosNum);
}
}

これで選択されたスプライトが判断できます。

準備ができたのでcsvファイルの処理を追加します。
PalletManager

using System.IO;

//フィールドデータをcsvに保存処理
public void CSVSeve()
{
string lineText=null;
StreamWriter sw;
FileInfo fi;
fi = new FileInfo(Application.dataPath + "/Resources/DataText/" + "FloorDate.csv");
sw = fi.AppendText();

for (int i = 0; i < 36; i++)
{
if (i % 6 == 0)
{
lineText = lineText + FieldPosition[i].ToString();
}
else
{
lineText = lineText + "," + FieldPosition[i].ToString();
}

if ( i % 6 == 5)
{
sw.WriteLine(lineText);
lineText = null;
}
}
sw.Close();
}

StreamWriterを使うので、System.IOを宣言します。

処理の中身ですが、
lineTextは各ポジションデータを取得する為の仮変数です。

StreamWriterの内容は、割愛します。

ループの中身なんですが…
以前も取り上げましたが、csvはカンマで区切る事で文字を分離する事ができます。

今のポジションデータを、そのまま羅列すると一つの文字として扱われてしまうので、
ポジション毎にカンマを挟む必要があります。

なので、左縦列のデータは、そのまま書き込みして、
残りは、頭にカンマを付けます。

判断の処理は、ループ数iを6で割った時に余りが出なければ、
左端と判断して、そのまま仮変数に代入します。

右端まで行くと次の行に移る必要があるので、
変数iを6で割り余りが5の時は、右端と判断しています。

剰余についてはGoogle先生にお尋ね下さい。

右端まで仮変数にナンバーを書き込んだ所でファイルに流します。
流し終わったら仮変数をリセットして、次の行に移ります。

スクリプトが組めたので、動作確認でっす。
MapTest⑮.jpg
この配列で保存してみます。

MapTest⑯.jpg
出来たファイルをエクセルで開くと…
無事配列通りに保存できてます。

簡易マップエディターは、以上となります。

マップデータ作成は面倒なので、簡単にデータ化できると楽になります。

最後に完成版のスクリプトを載せておきます。
PalletManager

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

public class PalletManager : MonoBehaviour
{
private int SelectSprite; //パレットの選択ボタンナンバー
private int[] FieldPosition = new int[36]; //各ポジションのスプライトナンバー

private bool Clear; //スプライトをnullにするフラグ変数
private int count; //フィールドボタンのカウント変数

// Start is called before the first frame update
void Start()
{

}

// Update is called once per frame
void Update()
{

}

//各ポジションのスプライトナンバーを取得
public void SetPosition(int pos)
{
FieldPosition[pos] = SelectSprite;
}

//オールクリアを押した処理
public void AllClear()
{
ACProperty = true;
}

//各ボタンのクリアが出来たかカウントする
public void SignCount()
{
count++;
if (count == 36)
{
Array.Clear(FieldPosition, 0, FieldPosition.Length);
ACProperty = false;
count = 0;
}
}

//選択スプライトの数値を管理
public int SelectProperty
{
get { return SelectSprite; }
set { SelectSprite = value; }
}

//オールクリア時の指示を各ボタンに送る
public bool ACProperty
{
get{ return Clear; }
set { Clear = value; }
}


//フィールドデータをcsvに保存処理
public void CSVSeve()
{
string lineText=null;
StreamWriter sw;
FileInfo fi;
fi = new FileInfo(Application.dataPath + "/Resources/DataText/" + "FloorDate.csv");
sw = fi.AppendText();

for (int i = 0; i < 36; i++)
{
if (i % 6 == 0)
{
lineText = lineText + FieldPosition[i].ToString();
}
else
{
lineText = lineText + "," + FieldPosition[i].ToString();
}

if (i % 6 == 5)
{
sw.WriteLine(lineText);
lineText = null;
}
}
sw.Close();
}
}


PalletButton

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

public class PalletButton : MonoBehaviour
{
public GameObject []Marker;       //各マーカーオブジェクト取得
public GameObject palletManager; //PalletManagerオブジェクト取得

private PalletManager palletM; //PalletManagerのキャッシュ変数


// Start is called before the first frame update
void Start()
{
palletM = palletManager.GetComponent<PalletManager>();
}

// Update is called once per frame
void Update()
{

}

//パレットボタンを押した時の処理
public void SelectButton(int num)
{
//選択中のナンバーと押したナンバーを比較
if (num == palletM.SelectProperty)
{
//ナンバーが同じならMarkerをfalseして0を登録
Marker[num].SetActive(false);
palletM.SelectProperty = 0;

//選択中のナンバーが0か確認
}else if (palletM.SelectProperty == 0)
{
//0なら押したナンバーのMarkerをtrueして登録
Marker[num].SetActive(true);
palletM.SelectProperty = num;
}
else
{
//選択中のMarkerをfalseして新規選択のMarkerをtrueして登録
Marker[palletM.SelectProperty].SetActive(false);
Marker[num].SetActive(true);
palletM.SelectProperty = num;
}
}
}


FieldButton

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

public class FieldButton : MonoBehaviour
{
public int PosNum;           //各ボタンのシリアルナンバー
public Sprite[] Pattern; //各スプライト取得
public GameObject palletManager; //PalletManager取得

private PalletManager palletM; //PalletManagerキャッシュ変数

private bool ACsign; //オールクリアのフラグ変数

// Start is called before the first frame update
void Start()
{
palletM = palletManager.GetComponent<PalletManager>();
}

// Update is called once per frame
void Update()
{
SignalCheck();
}

//フィールドボタンを押した処理
public void PushButton()
{
//マウスがクリックされてなければリターンする
if (Input.GetMouseButton(0) == false)
{
return;
}

//選択中のパレットナンバーからスプライトを取得
if (palletM.SelectProperty == 0)
{
//パレットナンバーが0ならスプライトを削除
this.gameObject.GetComponent<Image>().sprite = null;
palletM.SetPosition(PosNum);

}
else
{
//パレットナンバーにあったスプライトを表示する
this.gameObject.GetComponent<Image>().sprite = Pattern[palletM.SelectProperty];
palletM.SetPosition(PosNum);
}
}

//オールクリアのシグナルを判断する
void SignalCheck()
{
//オールクリアの指示判断
if (palletM.ACProperty && ACsign == false)
{
SpriteClear();
}
//オールクリア後の復旧判断
if (palletM.ACProperty == false && ACsign)
{
ACsign = false;
}
}

//オールクリア時の処理
void SpriteClear()
{
this.gameObject.GetComponent<Image>().sprite = null;
palletM.SignCount();
ACsign = true;
}
}

無事に完成できてよかったです。ヽ(´▽`)/~♪
これでパズル面を増やす時に楽になりそうです。

それでは今回はこの辺で。
(^ _ ^)/~~サヨナラ

この記事へのコメント