質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
Unity

Unityは、Unity Technologiesが開発・販売している、IDEを内蔵するゲームエンジンです。主にC#を用いたプログラミングでコンテンツの開発が可能です。

Q&A

解決済

2回答

9705閲覧

正しいCSVの書き出し方は?

fukkun0412

総合スコア37

Unity

Unityは、Unity Technologiesが開発・販売している、IDEを内蔵するゲームエンジンです。主にC#を用いたプログラミングでコンテンツの開発が可能です。

0グッド

3クリップ

投稿2016/05/31 13:03

編集2016/06/01 06:42

前回、質問したのと似たものですが、お許しください。
私は今、CSVを更新するためにCSVに書き込むプログラムを作成しています。
ソースを転記しておきます。
//一度読み込む
pathは"CSVData/bring"としています。
public void WriteCSV(string path){
TextAsset csv = Resources.Load(path) as TextAsset;
StringReader reader = new StringReader(csv.text);
StreamWriter sw;
FileInfo fi;
fi = new FileInfo(csv.name + ".csv");
sw = new StreamWriter(csv.name + ".csv", true);
sw.WriteLine("あかさたな");
sw.Flush();
sw.Close();
}

この方法だとpathの名前のCSVは作成されるのですが、場所が元の場所(Resources/CSVData/bring.csv)ではなくAssetsフォルダの外にできてしまいます。CSVファイルの中身の更新するのが目的なので、これではいけないのです。

そこでなのですが、皆さんに質問をしたいと思います。
・ファイル場所を変えずにCSVを更新する方法はあるのか?
・Resource.Loadのパスは相対パスで、StreamRenderは絶対パスで指定しなければならないが、どちらにあわせれば良いのか?(私的にはResources.Loadを使いたい)
・プラットフォーム関係なくCSVを更新するには?(できればResources.Loadに沿ってやりたい)

主にこの二つの質問に答えていただければ幸いです。(実際にソースを転記していただくと幸いです。)もし訂正箇所がありましたら、随時訂正いたします。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

shironegi

2016/06/01 00:11

同じファイルに書き込みたい動機は何なんでしょう。 セーブデータのように使いたいんでしょうか? それともCSVを編集するツールを作りたいんでしょうか? あと、前の質問とほぼ同じ質問を建てるなら、礼儀としてまず前の質問を何とかしましょうね。
fukkun0412

2016/06/01 06:06

はい。shironegiさんのおっしゃる通り、前の質問を締め切る前に似た質問してしまったのは反省します。書き込みたい動機は、データの更新です。解禁情報や成長過程などのデータを管理したいと思ったからです。
guest

回答2

0

ベストアンサー

追加情報ありがとうございます.

解禁情報や成長過程などのデータを管理したいと思ったからです。

つまりセーブデータということですね?

であれば,まずはゲームデータ(リソース)とセーブデータを切り分けて考えなければなりません.

ゲームデータはゲームの動作を定義するもので,予め用意されるものです.
セーブデータは,ゲームをプレイするにあたって生成され,書き換えられていくファイルなので,最初にゲームを起動した際は「空のファイル」または「ファイル自体無い」状態です.

つまり元からあるゲームデータを書き換えてセーブを実現しようというのは,ゲームというもののデータ管理の考え方と噛み合っていないのです.

したがって,セーブが目的であれば,
Resourcesフォルダ内のファイルを読みこんで上書きしていくのではなく,
ゲームデータの置き場所とは別の,セーブデータフォルダを用意して,
・セーブデータフォルダにファイルがあれば読み込んで,ファイルの内容を必要な変数に代入して保持
・進捗をセーブしたい時にセーブ関数を呼び出すと,セーブデータフォルダ内のファイルを上書きする
というようにするのが普通です.

前回の質問で,Application.dataPathで取得出来るパスは,プラットフォームによって書き込み出来ない場合があると書きましたが,書き込みが制限されている理由のひとつとして,ゲーム起動中にゲームデータが上書きされて,ゲームの動作がプレイ中に書き変わってしまわないように制限する目的があるのです.

実装について少し触れますが,
Resources.Loadはファイルの読み込みは出来ますが,保存はできません.
さらにマニュアルによるとResourcesフォルダ内のアセットしか読み込めないようです.
(http://docs.unity3d.com/ja/current/Manual/LoadingResourcesatRuntime.html)
したがってResourcesフォルダ外のセーブデータフォルダのファイルを読み込むにはStreamReaderを使用する必要があると思います.
保存にはStreamWriterを使用しなければなりません.
流れとしては,
・StreamReaderで既存のセーブデータファイルがあれば開く
・内容を読み込み内容を一旦変数に書きうつして閉じる
・(書き写した変数の中身を編集する)
・StreamWriterでセーブデータファイルを開いて内容を書き込んで閉じる.
となります.

上記を踏まえて質問の回答ですが,

・ファイル場所を変えずにCSVを更新する方法はあるのか?

読み込んだファイルと同じファイルパスで保存すれば,場所を変えずに保存できます.
(読み込み時にファイルを開いたままCloseしない状態だと書き込めないという実装上の注意点はありますが.)
今回の肝は3つ目だと思うので,そちらの回答を見て下さい.

・Resource.Loadのパスは相対パスで、StreamRenderは絶対パスで指定しなければならないが、どちらにあわせれば良いのか?(私的にはResources.Loadを使いたい)

読み込むことだけを考えれば,StreamReaderとResource.Loadは,どちらも読み込み機能しかありませんので,どちらでも構いません.
ただし書き込みにはStreamWriterを使わなければなりませんし,前述のようにResourcesフォルダ外であればStreamReaderでなければなりません.

・プラットフォーム関係なくCSVを更新するには?(できればResources.Loadに沿ってやりたい)

これを考えるならば,前提としてファイルの場所が「どのプラットフォームでも書き換え可能な場所」でなければなりません.
その為に,プラットフォームにあわせてパスが勝手に変わってくれるApplication.persistentDataPathが用意されているので,それを使用する他ありません.
プラットフォームが変わればApplication.persistentDataPathが変わるので,StreamReaderを使うしかないと思います.

具体的な方法やコード等が分からなければ聞いてもらえれば後ほど追加でお答えするとして,
その前にまずはセーブデータの扱い方について,ゲームデータと切り分けて考えてみてもらうことは可能でしょうか?

※ 質問内容から少しそれますが,
StreamReaderの代わりにFile.ReadAllText,StreamWriterの代わりにFile.WriteAllTextというものもあります.これらはファイルをCloseする必要がありませんし(ストリーミングしないため),使用方法もより単純です.
CSVファイルにこだわる理由は分かりませんが,セーブが目的なのであれば,UnityにはPlayerPrefsという仕組みが用意されており,これを使用すればファイル読み書きを気にすることなくセーブが実装出来ます.

投稿2016/06/01 10:36

編集2016/06/01 11:32
shironegi

総合スコア119

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

fukkun0412

2016/06/01 15:33

回答していただきありがとうございます。CSVファイルにこだわる理由は、クイズゲームを作成しておりまして、問題の管理をCSVファイルで行うと決め、他のファイルが別のものだと管理がしずらいのではないかと考えた末に全てのファイルをCSVファイルで管理しようと思ったのです。 質問なのですが、PlayerPrefsを使用すれば、質問の方で申し上げた、成長情報や解禁情報の管理も可能なのでしょうか?この情報は中身が変更するので、一体どうなるのか分からないので質問させていただきます。
shironegi

2016/06/02 10:18

なるほど. 問題文管理でCSVファイル入出力処理を作ってセーブにも使いまわそうという考えだったのですね. 経緯を知って納得しました. PlayerPrefsについて,詳しくは1から調べてみてもらえればと思いますが, 簡単にどんなものかと言うと,int, float, string の値を,自分で好きな名前を付けて保存・読み込みができ,ファイルへの書き出しもSave関数を呼び出せば自動で行ってくれて,アプリ起動時のファイル読み込みも自動で行ってくれるというものです. 自分で名前付けと保存する値のルールを決めればいいので,どんなデータにも対応できます. 例えばクイズの問題が1~10まであったとして, 1が正解済みであれば 名前を自分で決めて(たとえば"Question_1_is_Cleared"など),その名前で 1 を保存する,クリアできずにパスしていた場合は 0 を保存しておく事に決めておきます. クリアしたかどうか調べる場合には,名前を指定して値を読み込む関数があるので,「1が得られたらクリア済み」「0だったらクリアできなかった」「値が無かったら問題を見てすらいない」と進捗が判別できます. 私はゲーム開発に関しては,あるものは進んで利用するべきだという考えです. もちろん既存の方法では効率が悪くて(例えばデータの設定が面倒すぎて時間がかかったりして)とか,処理速度が遅くてとか,二進も三進もいかず仕組みを自作した方が良いと判断した場合は自作します. それ以外はせっかくUnityを使っているわけですし,よほどのこだわりが無ければ,出来る限りUnityの仕組みを利用するのが良いと思いますよ. 最近のゲーム開発はプロの現場でもそんな感じです.
guest

0

GetAssetPathで取ったパスは使えませんか?

投稿2016/05/31 19:33

dojikko

総合スコア3939

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

fukkun0412

2016/06/01 06:31

GetAssetPathを使う際に引数がint instanceIDのパターンとObject assetObjectのパターンがあるのですが、私の質問のプログラムの場合だとどういった使い方なら、よろしいのでしょうか?
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問