【Unity】CSVでテキストデータを保存する

2019/07/22更新 (追記をしています。)

カレンダーにテキストが反映できるようになったので、
ここからが難しいデータの保存方法を考えてみます。

まず、PlayerPrefsを使った保存方法ですが、
PlayerPrefs.SetInt ("data",0)
キーを設定して、数値や文字列を保存する必要があります。

1つのデータを保存するのに1つのキーを付けないといけないので、
大量のデータを保存するには、向いてないと言うか無理です。(^.^;



何か良い方法がないかと検索してみると

ロジカルシンキンぐんっ! さんの
[Unity] データを保存する(外部ファイルCSV)
有益な情報ありがとうございます。m(_ _)m

このcsv形式で保存する方法を試してみます。


csvとは、Comma Separated Valueの略でExcelを使っている方なら
見覚えのあるファイル形式かと思います。

テキストデータを「,」カンマで区切った文字列で保存する方法で、
区切られた文字が一つの単語とみなされます。


例えば
「あああいいい」と保存して表示する時には、
あああ
いいい
としたい場合、

そのままでは分離しないので、
「あああ、いいい」と保存します。
カンマで区切る事で別々のテキストとして読み込む事ができます。
今回のデータ保存にはおあつらえ向きの保存方法かと思います。


ここでお詫びです。
前々回にInputFoamManagerスクリプトをImageFoamにアタッチしたのですが、
スクリプトをFindする際にImageFoamが消えてるとエラーが出るので、
修正します。

ブログを見て作成されてる方はいないと思いますが、
ここまで作って修正しないといけない方には申し訳ありません。m(_ _)m



Hierarchyに空のオブジェクトを2つ作成して、
それぞれ、InputFoamManager、SaveManagerとします。
Calendar22.jpg
SaveManagerスクリプトを作成して、
それぞれのオブジェクトにアタッチします。

InputFoamManagerの各変数、各ボタンのOnClickを再設定して、
前々回の記事を参考にして下さい。m(_ _)m


ここからcsvの保存処理を作成していきます。

まずエディターでボタンを追加してセーブ用とします。

SaveManagerにSaveCSVメソッドを作成して、
ロジカルシンキンぐんっ!さんの書き込みコードを流用します。


public void SaveCSV()
{

StreamWriter sw = new StreamWriter(@"program.csv", false, Encoding.GetEncoding("Shift_JIS"));

// StreamWriterを閉じる
sw.Close();
}


セーブ用ボタンのOnClickに上記コードを割り当てます。

Calendar25.jpg

セーブの準備ができたので、
テキストデータをInputFoamManagerから渡さないといけないのですが、
渡したテキストを格納できるように変数を用意します。

37枠分の配列変数を用意して、
更新したテキストを格納して保存処理に使います。

続いてInputFoamManagerからテキストを渡す処理なんですが、
スクリプト間の変数共有には

・static変数
・GetSetで変数を共有
・引数で渡す

とあるのですが、今回は引数で渡してみようと思います。


InputFoamManager

private GameObject SaveManager; //SaveManagerオブジェクト取得変数

// Use this for initialization
void Start()
{
SaveManager = GameObject.Find("SaveManager");
}

InputFoamManagerからSaveManagerにアクセスする為、
SaveManagerをFindして変数にキャッシュしておきます。

続いて、カレンダー上にテキストを反映するメッソド内に
テキストをSaveManagerに渡す処理を追加します。

InputFoamManager

public void CalendarRef()
{
DayText = CARDText + "\n" + ChText + "\n" + TimeText;
CalendarText[FrameNo].GetComponent<Text>() .text= DayText;

//改行部分をカンマに変更してSaveManagerに渡す
string saveTx = CARDText + "," + ChText + "," + TimeText;
SaveManager.GetComponent<SaveManager>().OverWrite(FrameNo, saveTx);

//反映後入力フォームを閉じる
ImageFome.SetActive(false);
}

追加したのは、
string saveTx = CARDText + "," + ChText + "," + TimeText;
SaveManager.GetComponent<SaveManager>().OverWrite(FrameNo, saveTx);

の2行です。

DayTextをそのまま渡すとcsvにした時に\nで改行されてしまうので、
,に書き直す必要があります。

saveTxとFrameNoを引数にSaveManagerのOverWriteメソッドを呼び出します。

InputFoamManagerの準備ができたので、
SaveManagerに渡したテキストデータを格納する
OverWriteのメソッドを追加します。

SaveManager

public void OverWrite(int No, string Tx)
{
DayTx[No] = Tx;
}

単純です。(^.^; オホホホ
SaveCSVメソッドに書き加えようかと思ったのですが、
テキストを渡す度に書き込みが行われてしまうのも大変なので、
あえて格納するだけの処理にしてみました。

これで、テキストデータが更新できるようになったので、
格納変数をcsvファイルに書き込みしていきます。

SaveManager

public void SaveCSV()
{
StreamWriter sw = new StreamWriter(@"program.csv", false, Encoding.GetEncoding("Shift_JIS"));
// データ出力
for (int i = 0; i < 37; i++)
{
sw.WriteLine(DayTx[i]);
}
// StreamWriterを閉じる
sw.Close();
}

あとは格納したテキストをそのまま書き込むだけです。

実際に試してみます。

Calendar23.jpg
枠番6と枠番10に適当にテキストを選択して、
セーブボタンを押してみます。

Projectフォルダ直下にcsvファイルが作成されるので、
Excelで開いてみると
Calendar24.jpg
無事6枠と10枠に書き込まれています。

これで、カレンダー上のテキストを保存する事ができるようになりました。

最後に完成版のスクリプトを
SaveManager

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

public class SaveManager : MonoBehaviour
{

private string[] DayTx = new string[37];     //日ごとのテキストを格納する変数

// Use this for initialization
void Start()
{

}

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

}

//保存処理
public void SaveCSV()
{

StreamWriter sw = new StreamWriter(@"program.csv", false, Encoding.GetEncoding("Shift_JIS"));
// データ出力
for (int i = 0; i < 37; i++)
{
sw.WriteLine(DayTx[i]);
}
// StreamWriterを閉じる
sw.Close();
}

//更新したテキストを上書きする
public void OverWrite(int No, string Tx)
{
DayTx[No] = Tx;
}
}


InputFoamManager

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

public class InputFoamManager : MonoBehaviour
{

public GameObject ImageFome; //入力フォーム取得
public GameObject CARDView; //対戦カードView取得
public GameObject ChView; //放送ChView取得
public GameObject TimeView; //放送時間View取得

public GameObject TextCARD; //CARDViewボタンのテキスト取得
public GameObject TextCh; //ChViewボタンのテキスト取得
public GameObject TextTime; //TimeViewボタンのテキスト取得
public GameObject[] CalendarText; //カレンダー上のテキストを取得

private int ViewBt; //ビューボタンの番号変数
private int FrameNo; //カレンダーの枠番変数

private string CARDText, ChText, TimeText, DayText; //各テキスト

private GameObject SaveManager; //SaveManagerオブジェクト取得変数

// Use this for initialization
void Start()
{
SaveManager = GameObject.Find("SaveManager");
}

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

}

//各ScrollView呼び出し
public void ScrollViewCall(int Bt)
{
//いずれかのViewが開いてる時は他のViewは開かない
if (CARDView.activeSelf || ChView.activeSelf || TimeView.activeSelf)
{
return;
}

ViewBt = Bt; //クラス内でボタンナンバーを共有

switch (Bt)
{
case 1:
CARDView.SetActive(true);
break;

case 2:
ChView.SetActive(true);
break;

case 3:
TimeView.SetActive(true);
break;
}
}

//入力フォームを閉じる
public void Pushclose()
{
//いずれかのViewが開いている時はフォームを閉じない
if (CARDView.activeSelf || ChView.activeSelf || TimeView.activeSelf)
{
return;
}
ImageFome.SetActive(false);
}


//各Viewボタンのテキストに反映する
public void ViewTextRef(string Tx)
{
switch (ViewBt)
{
case 1:
TextCARD.GetComponent<Text>().text = Tx;
CARDText = Tx;
CARDView.SetActive(false);
break;

case 2:
TextCh.GetComponent<Text>().text = Tx;
ChText = Tx;
ChView.SetActive(false);
break;

case 3:
TextTime.GetComponent<Text>().text = Tx;
TimeText = Tx;
TimeView.SetActive(false);
break;
}
}


//カレンダーの日毎のボタンを押した処理
public void PushDayButton(int frame)
{
if (ImageFome.activeSelf)
{
return;
}

//入力フォームを開く
ImageFome.SetActive(true);
FrameNo = frame;
}


//カレンダー上にテキストを反映させる
public void CalendarRef()
{
DayText = CARDText + "\n" + ChText + "\n" + TimeText;
CalendarText[FrameNo].GetComponent<Text>() .text= DayText;

//改行部分をカンマに変更してSaveManagerに渡す
string saveTx = CARDText + "," + ChText + "," + TimeText;
SaveManager.GetComponent<SaveManager>().OverWrite(FrameNo, saveTx);

//反映後入力フォームを閉じる
ImageFome.SetActive(false);
}
}

相変わらずダラダラと長いコードでっす。(´`;)
上手く書けてるのか…

プロから見たら なんじゃこりゃ!(°∇°;)
って言われそうです。

コードさらすのってなんか恥ずかしいですね~(;^_^A



追記
SaveManagerの保存処理についてですが、
StreamWriterコマンドを使う時は、名前空間に
using System.Text;
using System.IO;


2つの宣言が無いとエラーがかかります。
説明不足で申し訳ありません(_ _(--;(_ _(--; pekopeko

この記事へのコメント