2014年12月16日火曜日

Unity4.2:文字コードとセーブファイルで困った・・・

以下始めてセーブファイルを作ろうとしたわけで馬鹿とか言わないで

セーブファイルの書式を決めようぜ
まずはセーブファイルの書式を決めるんだけど、ファイルの読み込みってこんな感じでやる。
var lineArray    = saveFile.text.Split("\n"[0]);
for each ( var str:String in lineArray){
     何か処理
}
つまり、全部Stringで戻ってくる。
だから、例えばbooleanとかintegerとかfloatで値を格納しても文字列になっちゃう。
つーことで、戻ってきた値を適切に処理できるように、以下のような書式にした。
項目名:型:値
例えば、(debug:bool:false)みたいな感じ。(何故かコロンを英数字にすると絵文字が出ちゃうので日本語で)
これを行ごとに処理してく。

各項目を処理しようとしたんだけど・・・
で、戻ってきた文字列を処理しようとして以下のようにしたんだけど。
var lineArray    = saveFile.text.Split("\n"[0]);
for each ( var str:String in lineArray){
     if ( str.Split(“:”[0])[0] == “true”){
          return(true);   //文字列trueをboolのtrueとして返す
     }else{
          return(false);   //文字列falseだったらboolのfalseとして返す
     }
}
なぜか全部falseになってしまう・・・
んで色々調べてみたら、どうもUTF-8という文字コードじゃないとちゃんと動かないらしい。
つまり、文字コードが違ったので、同じ”true”同士でも、同じと判別してくれてないみたい。
なので、書き込み部分をUTF-8で行うように変更する・・・

UTF-8で書き込むぜ!
色々省くけど、こんな感じ。
var sw            :StreamWriter;
var enc            :Encoding = Encoding.GetEncoding("UTF-8");
sw                 = new StreamWriter(saveFilePath, false, enc);
sw.WriteLine(“debug:bool:false”);
sw.Close();
で、ね。
うまくいかないわけよ!!!!!

更に調べると改行コードも関係してた
何か色々とエンコード回りを調べてたら、僕が作ったファイルはUTF-8になってるんだけど、
改行コード「混在」となってる・・・
更に調べるとUnityではUTF-8で改行コードCR LFじゃないとダメみたい。
僕の作ったファイルはCR LFとLFが混在してるわけ。
で、行ごとに読み込む時にSplit(“/n”[0])で読み込んでるので、これだとLFで切り分けてしまうので、CRが残ってしまうらしい。
CRは\rで表すらしいので、”true\r”と”true”を比べていたわけ!

わかったよ改行コードCR LFで書き込むよ
と・・・いったものの、書き込み方がわかんない・・・・
つーわけで一時間程あれこれ調べた結果、あきらめましたよ!

セーブファイルの書式を変えますよええ
LFで区切ってる場合とCR LFで区切っている場合を分けて処理使用とも考えたけど面倒なので、セーブファイルの書式を変えました。
項目名:型:値:
これで、CRは:でSplitされた時点で戻り値の行列の末尾にサヨナラだ!

そしてAndroidでセーブファイルがみつからない・・・
Windowsで作業した時にはわからなかったんだけど、Andoroidに出力したらセーブファイルみつからないよ・・・
つーわけで、ここからはそっちの探索をはじめます・・・・

続く・・・

2014年12月15日月曜日

Unity4.2:違うシーンをロードしても変数の内容を消さない

タイトル>ゲーム>タイトル>ゲーム
の繰り返しをするとして、ゲーム中に変更したオプションなんかを、一度タイトルに戻った後でも継続して持っていたい!
というわけで、調べたら(ちょっとどのサイトだったか忘れた)、ありました。

DontDestroyOnLoad (this);

これをしておけば、LoadLevelした時に、スクリプトがアサインされているオブジェクトが消えません。

//ObjAはインスタンス化しておく
--ObjA
-scriptA
function Awake(){
    DontDestroyOnLoad (this);
}


やったー!
って・・・
ロードするたびにオブジェクトが増える!

というわけで、一工夫。
先ほどのオブジェクト(ObjA)をプレハブ化しておき、別のオブジェクトのスクリプトからロード時に呼び出させます。

--ObjB
-scriptB
var objA :GameObject;   //InspectorでObjAを登録しておく
if(GameObject.Find("/ObjA(Clone)") == null){   //(Clone)で探す
    Instantiate(ObjA, Vector3(0,0,0), Quaternion.identity);
}


これで、シーンがロードされるたびに、壊したくないオブジェクトがあるか無いか判断して、あったら作りません。
ここで注意は(Clone)を付けておくっていうこと。
if文がいつまでたってもtrueにならなくて困りました。